From 1ae4b0f8f6c885543abd6d7a185e03f656004b1b Mon Sep 17 00:00:00 2001 From: Marius Vlad Date: Fri, 20 Apr 2012 23:38:17 +0300 Subject: [PATCH] * add p cc --- compilers/pcc/pcc-1.0.0/CVS/Entries | 14 + compilers/pcc/pcc-1.0.0/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/DATESTAMP | 1 + compilers/pcc/pcc-1.0.0/Makefile.in | 34 + compilers/pcc/pcc-1.0.0/arch/CVS/Entries | 13 + compilers/pcc/pcc-1.0.0/arch/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/arch/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/arch/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/arch/amd64/CVS/Entries | 7 + compilers/pcc/pcc-1.0.0/arch/amd64/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/arch/amd64/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/arch/amd64/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/arch/amd64/code.c | 973 +++ compilers/pcc/pcc-1.0.0/arch/amd64/local.c | 1266 ++++ compilers/pcc/pcc-1.0.0/arch/amd64/local2.c | 1185 ++++ compilers/pcc/pcc-1.0.0/arch/amd64/macdefs.h | 286 + compilers/pcc/pcc-1.0.0/arch/amd64/order.c | 358 ++ compilers/pcc/pcc-1.0.0/arch/amd64/table.c | 1594 +++++ compilers/pcc/pcc-1.0.0/arch/arm/CVS/Entries | 7 + compilers/pcc/pcc-1.0.0/arch/arm/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/arch/arm/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/arch/arm/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/arch/arm/code.c | 889 +++ compilers/pcc/pcc-1.0.0/arch/arm/local.c | 816 +++ compilers/pcc/pcc-1.0.0/arch/arm/local2.c | 1496 +++++ compilers/pcc/pcc-1.0.0/arch/arm/macdefs.h | 263 + compilers/pcc/pcc-1.0.0/arch/arm/order.c | 339 ++ compilers/pcc/pcc-1.0.0/arch/arm/table.c | 1847 ++++++ compilers/pcc/pcc-1.0.0/arch/hppa/CVS/Entries | 7 + compilers/pcc/pcc-1.0.0/arch/hppa/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/arch/hppa/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/arch/hppa/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/arch/hppa/code.c | 277 + compilers/pcc/pcc-1.0.0/arch/hppa/local.c | 994 ++++ compilers/pcc/pcc-1.0.0/arch/hppa/local2.c | 879 +++ compilers/pcc/pcc-1.0.0/arch/hppa/macdefs.h | 473 ++ compilers/pcc/pcc-1.0.0/arch/hppa/order.c | 216 + compilers/pcc/pcc-1.0.0/arch/hppa/table.c | 1014 ++++ compilers/pcc/pcc-1.0.0/arch/i386/CVS/Entries | 8 + compilers/pcc/pcc-1.0.0/arch/i386/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/arch/i386/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/arch/i386/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/arch/i386/code.c | 431 ++ compilers/pcc/pcc-1.0.0/arch/i386/flocal.c | 234 + compilers/pcc/pcc-1.0.0/arch/i386/local.c | 1574 +++++ compilers/pcc/pcc-1.0.0/arch/i386/local2.c | 1602 +++++ compilers/pcc/pcc-1.0.0/arch/i386/macdefs.h | 374 ++ compilers/pcc/pcc-1.0.0/arch/i386/order.c | 313 + compilers/pcc/pcc-1.0.0/arch/i386/table.c | 1643 ++++++ compilers/pcc/pcc-1.0.0/arch/m16c/CVS/Entries | 8 + compilers/pcc/pcc-1.0.0/arch/m16c/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/arch/m16c/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/arch/m16c/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/arch/m16c/TODO | 1 + compilers/pcc/pcc-1.0.0/arch/m16c/code.c | 350 ++ compilers/pcc/pcc-1.0.0/arch/m16c/local.c | 519 ++ compilers/pcc/pcc-1.0.0/arch/m16c/local2.c | 664 +++ compilers/pcc/pcc-1.0.0/arch/m16c/macdefs.h | 196 + compilers/pcc/pcc-1.0.0/arch/m16c/order.c | 621 ++ compilers/pcc/pcc-1.0.0/arch/m16c/table.c | 587 ++ compilers/pcc/pcc-1.0.0/arch/mips/CVS/Entries | 8 + compilers/pcc/pcc-1.0.0/arch/mips/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/arch/mips/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/arch/mips/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/arch/mips/TODO | 2 + compilers/pcc/pcc-1.0.0/arch/mips/code.c | 726 +++ compilers/pcc/pcc-1.0.0/arch/mips/local.c | 926 +++ compilers/pcc/pcc-1.0.0/arch/mips/local2.c | 1329 +++++ compilers/pcc/pcc-1.0.0/arch/mips/macdefs.h | 350 ++ compilers/pcc/pcc-1.0.0/arch/mips/order.c | 259 + compilers/pcc/pcc-1.0.0/arch/mips/table.c | 1580 +++++ compilers/pcc/pcc-1.0.0/arch/nova/CVS/Entries | 8 + compilers/pcc/pcc-1.0.0/arch/nova/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/arch/nova/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/arch/nova/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/arch/nova/README | 120 + compilers/pcc/pcc-1.0.0/arch/nova/code.c | 193 + compilers/pcc/pcc-1.0.0/arch/nova/local.c | 650 ++ compilers/pcc/pcc-1.0.0/arch/nova/local2.c | 580 ++ compilers/pcc/pcc-1.0.0/arch/nova/macdefs.h | 189 + compilers/pcc/pcc-1.0.0/arch/nova/order.c | 186 + compilers/pcc/pcc-1.0.0/arch/nova/table.c | 1514 +++++ compilers/pcc/pcc-1.0.0/arch/pdp10/CVS/Entries | 8 + compilers/pcc/pcc-1.0.0/arch/pdp10/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/arch/pdp10/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/arch/pdp10/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/arch/pdp10/README | 20 + compilers/pcc/pcc-1.0.0/arch/pdp10/code.c | 223 + compilers/pcc/pcc-1.0.0/arch/pdp10/local.c | 878 +++ compilers/pcc/pcc-1.0.0/arch/pdp10/local2.c | 1321 +++++ compilers/pcc/pcc-1.0.0/arch/pdp10/macdefs.h | 247 + compilers/pcc/pcc-1.0.0/arch/pdp10/order.c | 202 + compilers/pcc/pcc-1.0.0/arch/pdp10/table.c | 1136 ++++ compilers/pcc/pcc-1.0.0/arch/pdp11/CVS/Entries | 7 + compilers/pcc/pcc-1.0.0/arch/pdp11/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/arch/pdp11/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/arch/pdp11/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/arch/pdp11/code.c | 197 + compilers/pcc/pcc-1.0.0/arch/pdp11/local.c | 658 +++ compilers/pcc/pcc-1.0.0/arch/pdp11/local2.c | 845 +++ compilers/pcc/pcc-1.0.0/arch/pdp11/macdefs.h | 237 + compilers/pcc/pcc-1.0.0/arch/pdp11/order.c | 249 + compilers/pcc/pcc-1.0.0/arch/pdp11/table.c | 843 +++ compilers/pcc/pcc-1.0.0/arch/powerpc/CVS/Entries | 8 + .../pcc/pcc-1.0.0/arch/powerpc/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/arch/powerpc/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/arch/powerpc/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/arch/powerpc/README | 48 + compilers/pcc/pcc-1.0.0/arch/powerpc/code.c | 1541 +++++ compilers/pcc/pcc-1.0.0/arch/powerpc/local.c | 1512 +++++ compilers/pcc/pcc-1.0.0/arch/powerpc/local2.c | 1517 +++++ compilers/pcc/pcc-1.0.0/arch/powerpc/macdefs.h | 407 ++ compilers/pcc/pcc-1.0.0/arch/powerpc/order.c | 408 ++ compilers/pcc/pcc-1.0.0/arch/powerpc/table.c | 1806 ++++++ compilers/pcc/pcc-1.0.0/arch/sparc64/CVS/Entries | 7 + .../pcc/pcc-1.0.0/arch/sparc64/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/arch/sparc64/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/arch/sparc64/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/arch/sparc64/code.c | 242 + compilers/pcc/pcc-1.0.0/arch/sparc64/local.c | 350 ++ compilers/pcc/pcc-1.0.0/arch/sparc64/local2.c | 425 ++ compilers/pcc/pcc-1.0.0/arch/sparc64/macdefs.h | 266 + compilers/pcc/pcc-1.0.0/arch/sparc64/order.c | 115 + compilers/pcc/pcc-1.0.0/arch/sparc64/table.c | 963 +++ compilers/pcc/pcc-1.0.0/arch/vax/CVS/Entries | 7 + compilers/pcc/pcc-1.0.0/arch/vax/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/arch/vax/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/arch/vax/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/arch/vax/code.c | 330 ++ compilers/pcc/pcc-1.0.0/arch/vax/local.c | 511 ++ compilers/pcc/pcc-1.0.0/arch/vax/local2.c | 1036 ++++ compilers/pcc/pcc-1.0.0/arch/vax/macdefs.h | 259 + compilers/pcc/pcc-1.0.0/arch/vax/order.c | 611 ++ compilers/pcc/pcc-1.0.0/arch/vax/table.c | 695 +++ compilers/pcc/pcc-1.0.0/cc/CVS/Entries | 5 + compilers/pcc/pcc-1.0.0/cc/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/cc/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/cc/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/cc/Makefile.in | 39 + compilers/pcc/pcc-1.0.0/cc/cc/CVS/Entries | 4 + compilers/pcc/pcc-1.0.0/cc/cc/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/cc/cc/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/cc/cc/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/cc/cc/Makefile.in | 70 + compilers/pcc/pcc-1.0.0/cc/cc/cc.1 | 335 ++ compilers/pcc/pcc-1.0.0/cc/cc/cc.c | 1535 +++++ compilers/pcc/pcc-1.0.0/cc/ccom/CVS/Entries | 17 + compilers/pcc/pcc-1.0.0/cc/ccom/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/cc/ccom/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/cc/ccom/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/cc/ccom/Makefile.in | 139 + compilers/pcc/pcc-1.0.0/cc/ccom/builtins.c | 638 ++ compilers/pcc/pcc-1.0.0/cc/ccom/ccom.1 | 192 + compilers/pcc/pcc-1.0.0/cc/ccom/cgram.y | 2259 +++++++ compilers/pcc/pcc-1.0.0/cc/ccom/gcc_compat.c | 574 ++ compilers/pcc/pcc-1.0.0/cc/ccom/init.c | 1060 ++++ compilers/pcc/pcc-1.0.0/cc/ccom/inline.c | 538 ++ compilers/pcc/pcc-1.0.0/cc/ccom/main.c | 397 ++ compilers/pcc/pcc-1.0.0/cc/ccom/optim.c | 385 ++ compilers/pcc/pcc-1.0.0/cc/ccom/pass1.h | 611 ++ compilers/pcc/pcc-1.0.0/cc/ccom/pftn.c | 3271 ++++++++++ compilers/pcc/pcc-1.0.0/cc/ccom/scan.l | 773 +++ compilers/pcc/pcc-1.0.0/cc/ccom/softfloat.c | 359 ++ compilers/pcc/pcc-1.0.0/cc/ccom/stabs.c | 459 ++ compilers/pcc/pcc-1.0.0/cc/ccom/symtabs.c | 360 ++ compilers/pcc/pcc-1.0.0/cc/ccom/trees.c | 2896 +++++++++ compilers/pcc/pcc-1.0.0/cc/cpp/CVS/Entries | 9 + compilers/pcc/pcc-1.0.0/cc/cpp/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/cc/cpp/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/cc/cpp/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/cc/cpp/Makefile.in | 105 + compilers/pcc/pcc-1.0.0/cc/cpp/cpp.1 | 210 + compilers/pcc/pcc-1.0.0/cc/cpp/cpp.c | 1971 +++++++ compilers/pcc/pcc-1.0.0/cc/cpp/cpp.h | 184 + compilers/pcc/pcc-1.0.0/cc/cpp/cpy.y | 221 + compilers/pcc/pcc-1.0.0/cc/cpp/scanner.l | 939 +++ compilers/pcc/pcc-1.0.0/cc/cpp/tests/CVS/Entries | 27 + .../pcc/pcc-1.0.0/cc/cpp/tests/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/res1 | 8 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/res10 | 16 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/res11 | 22 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/res12 | 21 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/res13 | 13 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/res2 | 27 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/res3 | 16 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/res4 | 6 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/res5 | 5 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/res6 | 5 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/res7 | 6 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/res8 | 9 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/res9 | 6 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/test1 | 6 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/test10 | 14 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/test11 | 20 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/test12 | 19 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/test13 | 11 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/test2 | 25 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/test3 | 15 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/test4 | 4 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/test5 | 3 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/test6 | 5 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/test7 | 4 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/test8 | 7 + compilers/pcc/pcc-1.0.0/cc/cpp/tests/test9 | 4 + compilers/pcc/pcc-1.0.0/cc/cpp/token.c | 1318 +++++ compilers/pcc/pcc-1.0.0/config.guess | 1516 +++++ compilers/pcc/pcc-1.0.0/config.h.in | 176 + compilers/pcc/pcc-1.0.0/config.sub | 1658 ++++++ compilers/pcc/pcc-1.0.0/configure | 6240 ++++++++++++++++++++ compilers/pcc/pcc-1.0.0/configure.ac | 482 ++ compilers/pcc/pcc-1.0.0/f77/CVS/Entries | 4 + compilers/pcc/pcc-1.0.0/f77/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/f77/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/f77/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/f77/Makefile.in | 36 + compilers/pcc/pcc-1.0.0/f77/f77/CVS/Entries | 4 + compilers/pcc/pcc-1.0.0/f77/f77/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/f77/f77/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/f77/f77/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/f77/f77/Makefile.in | 52 + compilers/pcc/pcc-1.0.0/f77/f77/f77.1 | 175 + compilers/pcc/pcc-1.0.0/f77/f77/f77.c | 796 +++ compilers/pcc/pcc-1.0.0/f77/fcom/CVS/Entries | 26 + compilers/pcc/pcc-1.0.0/f77/fcom/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/f77/fcom/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/f77/fcom/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/f77/fcom/Makefile.in | 121 + compilers/pcc/pcc-1.0.0/f77/fcom/data.c | 358 ++ compilers/pcc/pcc-1.0.0/f77/fcom/defines.h | 267 + compilers/pcc/pcc-1.0.0/f77/fcom/defs.h | 562 ++ compilers/pcc/pcc-1.0.0/f77/fcom/equiv.c | 309 + compilers/pcc/pcc-1.0.0/f77/fcom/error.c | 121 + compilers/pcc/pcc-1.0.0/f77/fcom/exec.c | 591 ++ compilers/pcc/pcc-1.0.0/f77/fcom/expr.c | 2179 +++++++ compilers/pcc/pcc-1.0.0/f77/fcom/ftypes.h | 82 + compilers/pcc/pcc-1.0.0/f77/fcom/gram.dcl | 318 + compilers/pcc/pcc-1.0.0/f77/fcom/gram.exec | 112 + compilers/pcc/pcc-1.0.0/f77/fcom/gram.expr | 125 + compilers/pcc/pcc-1.0.0/f77/fcom/gram.head | 174 + compilers/pcc/pcc-1.0.0/f77/fcom/gram.io | 156 + compilers/pcc/pcc-1.0.0/f77/fcom/init.c | 292 + compilers/pcc/pcc-1.0.0/f77/fcom/intr.c | 606 ++ compilers/pcc/pcc-1.0.0/f77/fcom/io.c | 797 +++ compilers/pcc/pcc-1.0.0/f77/fcom/lex.c | 955 +++ compilers/pcc/pcc-1.0.0/f77/fcom/main.c | 427 ++ compilers/pcc/pcc-1.0.0/f77/fcom/misc.c | 704 +++ compilers/pcc/pcc-1.0.0/f77/fcom/proc.c | 908 +++ compilers/pcc/pcc-1.0.0/f77/fcom/put.c | 299 + compilers/pcc/pcc-1.0.0/f77/fcom/putscj.c | 1451 +++++ compilers/pcc/pcc-1.0.0/f77/fcom/scjdefs.h | 37 + compilers/pcc/pcc-1.0.0/f77/fcom/tokens | 95 + compilers/pcc/pcc-1.0.0/install-sh | 294 + compilers/pcc/pcc-1.0.0/mip/CVS/Entries | 12 + compilers/pcc/pcc-1.0.0/mip/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/mip/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/mip/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/mip/common.c | 784 +++ compilers/pcc/pcc-1.0.0/mip/compat.c | 922 +++ compilers/pcc/pcc-1.0.0/mip/compat.h | 45 + compilers/pcc/pcc-1.0.0/mip/manifest.h | 380 ++ compilers/pcc/pcc-1.0.0/mip/match.c | 1260 ++++ compilers/pcc/pcc-1.0.0/mip/mkext.c | 474 ++ compilers/pcc/pcc-1.0.0/mip/node.h | 236 + compilers/pcc/pcc-1.0.0/mip/optim2.c | 2144 +++++++ compilers/pcc/pcc-1.0.0/mip/pass2.h | 546 ++ compilers/pcc/pcc-1.0.0/mip/reader.c | 1663 ++++++ compilers/pcc/pcc-1.0.0/mip/regs.c | 2869 +++++++++ compilers/pcc/pcc-1.0.0/os/CVS/Entries | 14 + compilers/pcc/pcc-1.0.0/os/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/os/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/os/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/os/bsd/CVS/Entries | 2 + compilers/pcc/pcc-1.0.0/os/bsd/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/os/bsd/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/os/bsd/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/os/bsd/ccconfig.h | 53 + compilers/pcc/pcc-1.0.0/os/darwin/CVS/Entries | 2 + compilers/pcc/pcc-1.0.0/os/darwin/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/os/darwin/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/os/darwin/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/os/darwin/ccconfig.h | 65 + compilers/pcc/pcc-1.0.0/os/dragonfly/CVS/Entries | 2 + .../pcc/pcc-1.0.0/os/dragonfly/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/os/dragonfly/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/os/dragonfly/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/os/dragonfly/ccconfig.h | 66 + compilers/pcc/pcc-1.0.0/os/freebsd/CVS/Entries | 2 + compilers/pcc/pcc-1.0.0/os/freebsd/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/os/freebsd/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/os/freebsd/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/os/freebsd/ccconfig.h | 62 + compilers/pcc/pcc-1.0.0/os/linux/CVS/Entries | 2 + compilers/pcc/pcc-1.0.0/os/linux/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/os/linux/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/os/linux/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/os/linux/ccconfig.h | 75 + compilers/pcc/pcc-1.0.0/os/midnightbsd/CVS/Entries | 2 + .../pcc/pcc-1.0.0/os/midnightbsd/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/os/midnightbsd/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/os/midnightbsd/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/os/midnightbsd/ccconfig.h | 131 + compilers/pcc/pcc-1.0.0/os/mirbsd/CVS/Entries | 2 + compilers/pcc/pcc-1.0.0/os/mirbsd/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/os/mirbsd/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/os/mirbsd/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/os/mirbsd/ccconfig.h | 108 + compilers/pcc/pcc-1.0.0/os/netbsd/CVS/Entries | 2 + compilers/pcc/pcc-1.0.0/os/netbsd/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/os/netbsd/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/os/netbsd/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/os/netbsd/ccconfig.h | 91 + compilers/pcc/pcc-1.0.0/os/nextstep/CVS/Entries | 2 + compilers/pcc/pcc-1.0.0/os/nextstep/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/os/nextstep/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/os/nextstep/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/os/nextstep/ccconfig.h | 66 + compilers/pcc/pcc-1.0.0/os/none/CVS/Entries | 2 + compilers/pcc/pcc-1.0.0/os/none/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/os/none/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/os/none/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/os/none/ccconfig.h | 50 + compilers/pcc/pcc-1.0.0/os/openbsd/CVS/Entries | 3 + compilers/pcc/pcc-1.0.0/os/openbsd/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/os/openbsd/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/os/openbsd/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/os/openbsd/ccconfig.h | 61 + compilers/pcc/pcc-1.0.0/os/openbsd/f77config.h | 46 + compilers/pcc/pcc-1.0.0/os/sunos/CVS/Entries | 2 + compilers/pcc/pcc-1.0.0/os/sunos/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/os/sunos/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/os/sunos/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/os/sunos/ccconfig.h | 71 + compilers/pcc/pcc-1.0.0/os/win32/CVS/Entries | 6 + compilers/pcc/pcc-1.0.0/os/win32/CVS/Repository | 1 + compilers/pcc/pcc-1.0.0/os/win32/CVS/Root | 1 + compilers/pcc/pcc-1.0.0/os/win32/CVS/Tag | 1 + compilers/pcc/pcc-1.0.0/os/win32/build.bat | 205 + .../pcc/pcc-1.0.0/os/win32/build_installer.bat | 1 + compilers/pcc/pcc-1.0.0/os/win32/ccconfig.h | 23 + compilers/pcc/pcc-1.0.0/os/win32/config.h | 81 + compilers/pcc/pcc-1.0.0/os/win32/pcc.iss | 93 + compilers/pcc/pcc-libs-1.0.0/CVS/Entries | 12 + compilers/pcc/pcc-libs-1.0.0/CVS/Repository | 1 + compilers/pcc/pcc-libs-1.0.0/CVS/Root | 1 + compilers/pcc/pcc-libs-1.0.0/CVS/Tag | 1 + compilers/pcc/pcc-libs-1.0.0/Makefile.in | 23 + compilers/pcc/pcc-libs-1.0.0/config.guess | 1516 +++++ compilers/pcc/pcc-libs-1.0.0/config.sub | 1626 +++++ compilers/pcc/pcc-libs-1.0.0/configure | 3385 +++++++++++ compilers/pcc/pcc-libs-1.0.0/configure.ac | 152 + compilers/pcc/pcc-libs-1.0.0/csu/CVS/Entries | 6 + compilers/pcc/pcc-libs-1.0.0/csu/CVS/Repository | 1 + compilers/pcc/pcc-libs-1.0.0/csu/CVS/Root | 1 + compilers/pcc/pcc-libs-1.0.0/csu/CVS/Tag | 1 + compilers/pcc/pcc-libs-1.0.0/csu/Makefile.in | 26 + compilers/pcc/pcc-libs-1.0.0/csu/README | 18 + .../pcc/pcc-libs-1.0.0/csu/darwin/CVS/Entries | 7 + .../pcc/pcc-libs-1.0.0/csu/darwin/CVS/Repository | 1 + compilers/pcc/pcc-libs-1.0.0/csu/darwin/CVS/Root | 1 + compilers/pcc/pcc-libs-1.0.0/csu/darwin/CVS/Tag | 1 + compilers/pcc/pcc-libs-1.0.0/csu/darwin/Makefile | 30 + compilers/pcc/pcc-libs-1.0.0/csu/darwin/common.c | 120 + compilers/pcc/pcc-libs-1.0.0/csu/darwin/common.h | 51 + .../pcc/pcc-libs-1.0.0/csu/darwin/i386/CVS/Entries | 3 + .../pcc-libs-1.0.0/csu/darwin/i386/CVS/Repository | 1 + .../pcc/pcc-libs-1.0.0/csu/darwin/i386/CVS/Root | 1 + .../pcc/pcc-libs-1.0.0/csu/darwin/i386/CVS/Tag | 1 + .../pcc/pcc-libs-1.0.0/csu/darwin/i386/crt0.c | 152 + .../pcc/pcc-libs-1.0.0/csu/darwin/i386/dylib1.c | 70 + compilers/pcc/pcc-libs-1.0.0/csu/darwin/macho.h | 58 + .../pcc-libs-1.0.0/csu/darwin/powerpc/CVS/Entries | 3 + .../csu/darwin/powerpc/CVS/Repository | 1 + .../pcc/pcc-libs-1.0.0/csu/darwin/powerpc/CVS/Root | 1 + .../pcc/pcc-libs-1.0.0/csu/darwin/powerpc/CVS/Tag | 1 + .../pcc/pcc-libs-1.0.0/csu/darwin/powerpc/crt0.c | 160 + .../pcc/pcc-libs-1.0.0/csu/darwin/powerpc/dylib1.c | 88 + compilers/pcc/pcc-libs-1.0.0/csu/linux/CVS/Entries | 8 + .../pcc/pcc-libs-1.0.0/csu/linux/CVS/Repository | 1 + compilers/pcc/pcc-libs-1.0.0/csu/linux/CVS/Root | 1 + compilers/pcc/pcc-libs-1.0.0/csu/linux/CVS/Tag | 1 + compilers/pcc/pcc-libs-1.0.0/csu/linux/Makefile | 39 + .../pcc/pcc-libs-1.0.0/csu/linux/amd64/CVS/Entries | 4 + .../pcc-libs-1.0.0/csu/linux/amd64/CVS/Repository | 1 + .../pcc/pcc-libs-1.0.0/csu/linux/amd64/CVS/Root | 1 + .../pcc/pcc-libs-1.0.0/csu/linux/amd64/CVS/Tag | 1 + .../pcc/pcc-libs-1.0.0/csu/linux/amd64/crt0.c | 53 + .../pcc/pcc-libs-1.0.0/csu/linux/amd64/crti.c | 34 + .../pcc/pcc-libs-1.0.0/csu/linux/amd64/crtn.c | 30 + compilers/pcc/pcc-libs-1.0.0/csu/linux/common.c | 24 + compilers/pcc/pcc-libs-1.0.0/csu/linux/common.h | 33 + compilers/pcc/pcc-libs-1.0.0/csu/linux/crtbegin.c | 123 + compilers/pcc/pcc-libs-1.0.0/csu/linux/crtend.c | 36 + .../pcc/pcc-libs-1.0.0/csu/linux/i386/CVS/Entries | 4 + .../pcc-libs-1.0.0/csu/linux/i386/CVS/Repository | 1 + .../pcc/pcc-libs-1.0.0/csu/linux/i386/CVS/Root | 1 + .../pcc/pcc-libs-1.0.0/csu/linux/i386/CVS/Tag | 1 + compilers/pcc/pcc-libs-1.0.0/csu/linux/i386/crt0.c | 57 + compilers/pcc/pcc-libs-1.0.0/csu/linux/i386/crti.c | 36 + compilers/pcc/pcc-libs-1.0.0/csu/linux/i386/crtn.c | 30 + .../pcc/pcc-libs-1.0.0/csu/netbsd/CVS/Entries | 5 + .../pcc/pcc-libs-1.0.0/csu/netbsd/CVS/Repository | 1 + compilers/pcc/pcc-libs-1.0.0/csu/netbsd/CVS/Root | 1 + compilers/pcc/pcc-libs-1.0.0/csu/netbsd/CVS/Tag | 1 + compilers/pcc/pcc-libs-1.0.0/csu/netbsd/Makefile | 24 + compilers/pcc/pcc-libs-1.0.0/csu/netbsd/common.h | 23 + compilers/pcc/pcc-libs-1.0.0/csu/netbsd/crtbegin.c | 119 + compilers/pcc/pcc-libs-1.0.0/csu/netbsd/crtend.c | 36 + compilers/pcc/pcc-libs-1.0.0/install-sh | 294 + compilers/pcc/pcc-libs-1.0.0/libF77/CVS/Entries | 114 + compilers/pcc/pcc-libs-1.0.0/libF77/CVS/Repository | 1 + compilers/pcc/pcc-libs-1.0.0/libF77/CVS/Root | 1 + compilers/pcc/pcc-libs-1.0.0/libF77/CVS/Tag | 1 + compilers/pcc/pcc-libs-1.0.0/libF77/Makefile | 33 + compilers/pcc/pcc-libs-1.0.0/libF77/abort_.c | 45 + compilers/pcc/pcc-libs-1.0.0/libF77/c_abs.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/c_cos.c | 44 + compilers/pcc/pcc-libs-1.0.0/libF77/c_div.c | 63 + compilers/pcc/pcc-libs-1.0.0/libF77/c_exp.c | 47 + compilers/pcc/pcc-libs-1.0.0/libF77/c_log.c | 45 + compilers/pcc/pcc-libs-1.0.0/libF77/c_sin.c | 45 + compilers/pcc/pcc-libs-1.0.0/libF77/c_sqrt.c | 55 + compilers/pcc/pcc-libs-1.0.0/libF77/cabs.c | 59 + compilers/pcc/pcc-libs-1.0.0/libF77/complex | 36 + compilers/pcc/pcc-libs-1.0.0/libF77/d_abs.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/d_acos.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/d_asin.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/d_atan.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/d_atn2.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/d_cnjg.c | 42 + compilers/pcc/pcc-libs-1.0.0/libF77/d_cos.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/d_cosh.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/d_dim.c | 41 + compilers/pcc/pcc-libs-1.0.0/libF77/d_erf.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/d_erfc.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/d_exp.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/d_imag.c | 41 + compilers/pcc/pcc-libs-1.0.0/libF77/d_int.c | 41 + compilers/pcc/pcc-libs-1.0.0/libF77/d_lg10.c | 44 + compilers/pcc/pcc-libs-1.0.0/libF77/d_log.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/d_mod.c | 41 + compilers/pcc/pcc-libs-1.0.0/libF77/d_nint.c | 42 + compilers/pcc/pcc-libs-1.0.0/libF77/d_prod.c | 41 + compilers/pcc/pcc-libs-1.0.0/libF77/d_sign.c | 44 + compilers/pcc/pcc-libs-1.0.0/libF77/d_sin.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/d_sinh.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/d_sqrt.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/d_tan.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/d_tanh.c | 42 + compilers/pcc/pcc-libs-1.0.0/libF77/erf.c | 150 + compilers/pcc/pcc-libs-1.0.0/libF77/f77lib.h | 113 + compilers/pcc/pcc-libs-1.0.0/libF77/getarg_.c | 58 + compilers/pcc/pcc-libs-1.0.0/libF77/h_abs.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/h_dim.c | 41 + compilers/pcc/pcc-libs-1.0.0/libF77/h_dnnt.c | 42 + compilers/pcc/pcc-libs-1.0.0/libF77/h_indx.c | 56 + compilers/pcc/pcc-libs-1.0.0/libF77/h_len.c | 41 + compilers/pcc/pcc-libs-1.0.0/libF77/h_mod.c | 41 + compilers/pcc/pcc-libs-1.0.0/libF77/h_nint.c | 42 + compilers/pcc/pcc-libs-1.0.0/libF77/h_sign.c | 44 + compilers/pcc/pcc-libs-1.0.0/libF77/hl_ge.c | 41 + compilers/pcc/pcc-libs-1.0.0/libF77/hl_gt.c | 41 + compilers/pcc/pcc-libs-1.0.0/libF77/hl_le.c | 41 + compilers/pcc/pcc-libs-1.0.0/libF77/hl_lt.c | 41 + compilers/pcc/pcc-libs-1.0.0/libF77/i_abs.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/i_dim.c | 41 + compilers/pcc/pcc-libs-1.0.0/libF77/i_dnnt.c | 42 + compilers/pcc/pcc-libs-1.0.0/libF77/i_indx.c | 56 + compilers/pcc/pcc-libs-1.0.0/libF77/i_len.c | 41 + compilers/pcc/pcc-libs-1.0.0/libF77/i_mod.c | 41 + compilers/pcc/pcc-libs-1.0.0/libF77/i_nint.c | 42 + compilers/pcc/pcc-libs-1.0.0/libF77/i_sign.c | 44 + compilers/pcc/pcc-libs-1.0.0/libF77/iargc_.c | 42 + compilers/pcc/pcc-libs-1.0.0/libF77/l_ge.c | 41 + compilers/pcc/pcc-libs-1.0.0/libF77/l_gt.c | 41 + compilers/pcc/pcc-libs-1.0.0/libF77/l_le.c | 41 + compilers/pcc/pcc-libs-1.0.0/libF77/l_lt.c | 41 + compilers/pcc/pcc-libs-1.0.0/libF77/main.c | 86 + compilers/pcc/pcc-libs-1.0.0/libF77/pow_ci.c | 49 + compilers/pcc/pcc-libs-1.0.0/libF77/pow_dd.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/pow_di.c | 65 + compilers/pcc/pcc-libs-1.0.0/libF77/pow_hh.c | 59 + compilers/pcc/pcc-libs-1.0.0/libF77/pow_ii.c | 59 + compilers/pcc/pcc-libs-1.0.0/libF77/pow_ri.c | 65 + compilers/pcc/pcc-libs-1.0.0/libF77/pow_zi.c | 71 + compilers/pcc/pcc-libs-1.0.0/libF77/pow_zz.c | 52 + compilers/pcc/pcc-libs-1.0.0/libF77/r_abs.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/r_acos.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/r_asin.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/r_atan.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/r_atn2.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/r_cnjg.c | 42 + compilers/pcc/pcc-libs-1.0.0/libF77/r_cos.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/r_cosh.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/r_dim.c | 41 + compilers/pcc/pcc-libs-1.0.0/libF77/r_erf.c | 40 + compilers/pcc/pcc-libs-1.0.0/libF77/r_erfc.c | 40 + compilers/pcc/pcc-libs-1.0.0/libF77/r_exp.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/r_imag.c | 41 + compilers/pcc/pcc-libs-1.0.0/libF77/r_int.c | 41 + compilers/pcc/pcc-libs-1.0.0/libF77/r_lg10.c | 44 + compilers/pcc/pcc-libs-1.0.0/libF77/r_log.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/r_mod.c | 41 + compilers/pcc/pcc-libs-1.0.0/libF77/r_nint.c | 42 + compilers/pcc/pcc-libs-1.0.0/libF77/r_sign.c | 44 + compilers/pcc/pcc-libs-1.0.0/libF77/r_sin.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/r_sinh.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/r_sqrt.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/r_tan.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/r_tanh.c | 43 + compilers/pcc/pcc-libs-1.0.0/libF77/s_cat.c | 55 + compilers/pcc/pcc-libs-1.0.0/libF77/s_cmp.c | 66 + compilers/pcc/pcc-libs-1.0.0/libF77/s_copy.c | 55 + compilers/pcc/pcc-libs-1.0.0/libF77/s_paus.c | 77 + compilers/pcc/pcc-libs-1.0.0/libF77/s_rnge.c | 57 + compilers/pcc/pcc-libs-1.0.0/libF77/s_stop.c | 53 + compilers/pcc/pcc-libs-1.0.0/libF77/signal_.c | 49 + compilers/pcc/pcc-libs-1.0.0/libF77/sinh.c | 105 + compilers/pcc/pcc-libs-1.0.0/libF77/tanh.c | 61 + compilers/pcc/pcc-libs-1.0.0/libF77/z_abs.c | 44 + compilers/pcc/pcc-libs-1.0.0/libF77/z_cos.c | 45 + compilers/pcc/pcc-libs-1.0.0/libF77/z_div.c | 67 + compilers/pcc/pcc-libs-1.0.0/libF77/z_exp.c | 47 + compilers/pcc/pcc-libs-1.0.0/libF77/z_log.c | 45 + compilers/pcc/pcc-libs-1.0.0/libF77/z_sin.c | 45 + compilers/pcc/pcc-libs-1.0.0/libF77/z_sqrt.c | 55 + compilers/pcc/pcc-libs-1.0.0/libI77/CVS/Entries | 29 + compilers/pcc/pcc-libs-1.0.0/libI77/CVS/Repository | 1 + compilers/pcc/pcc-libs-1.0.0/libI77/CVS/Root | 1 + compilers/pcc/pcc-libs-1.0.0/libI77/CVS/Tag | 1 + compilers/pcc/pcc-libs-1.0.0/libI77/Makefile | 20 + compilers/pcc/pcc-libs-1.0.0/libI77/backspace.c | 89 + compilers/pcc/pcc-libs-1.0.0/libI77/close.c | 92 + compilers/pcc/pcc-libs-1.0.0/libI77/dfe.c | 162 + compilers/pcc/pcc-libs-1.0.0/libI77/due.c | 92 + compilers/pcc/pcc-libs-1.0.0/libI77/endfile.c | 101 + compilers/pcc/pcc-libs-1.0.0/libI77/err.c | 159 + compilers/pcc/pcc-libs-1.0.0/libI77/fio.h | 213 + compilers/pcc/pcc-libs-1.0.0/libI77/fmt.c | 446 ++ compilers/pcc/pcc-libs-1.0.0/libI77/fmt.h | 94 + compilers/pcc/pcc-libs-1.0.0/libI77/fmtlib.c | 60 + compilers/pcc/pcc-libs-1.0.0/libI77/iio.c | 145 + compilers/pcc/pcc-libs-1.0.0/libI77/inquire.c | 123 + compilers/pcc/pcc-libs-1.0.0/libI77/lib.c | 76 + compilers/pcc/pcc-libs-1.0.0/libI77/lio.c | 196 + compilers/pcc/pcc-libs-1.0.0/libI77/lio.h | 77 + compilers/pcc/pcc-libs-1.0.0/libI77/lread.c | 466 ++ compilers/pcc/pcc-libs-1.0.0/libI77/open.c | 157 + compilers/pcc/pcc-libs-1.0.0/libI77/pwd.c | 112 + compilers/pcc/pcc-libs-1.0.0/libI77/rdfmt.c | 289 + compilers/pcc/pcc-libs-1.0.0/libI77/rewind.c | 52 + compilers/pcc/pcc-libs-1.0.0/libI77/rsfe.c | 111 + compilers/pcc/pcc-libs-1.0.0/libI77/sfe.c | 63 + compilers/pcc/pcc-libs-1.0.0/libI77/sue.c | 109 + compilers/pcc/pcc-libs-1.0.0/libI77/uio.c | 84 + compilers/pcc/pcc-libs-1.0.0/libI77/util.c | 176 + compilers/pcc/pcc-libs-1.0.0/libI77/wrtfmt.c | 381 ++ compilers/pcc/pcc-libs-1.0.0/libI77/wsfe.c | 115 + compilers/pcc/pcc-libs-1.0.0/libpcc/CVS/Entries | 35 + compilers/pcc/pcc-libs-1.0.0/libpcc/CVS/Repository | 1 + compilers/pcc/pcc-libs-1.0.0/libpcc/CVS/Root | 1 + compilers/pcc/pcc-libs-1.0.0/libpcc/CVS/Tag | 1 + compilers/pcc/pcc-libs-1.0.0/libpcc/Makefile.in | 73 + compilers/pcc/pcc-libs-1.0.0/libpcc/_alloca.c | 42 + compilers/pcc/pcc-libs-1.0.0/libpcc/_ftol.asm | 26 + compilers/pcc/pcc-libs-1.0.0/libpcc/_ftol.c | 23 + compilers/pcc/pcc-libs-1.0.0/libpcc/adddi3.c | 54 + compilers/pcc/pcc-libs-1.0.0/libpcc/anddi3.c | 52 + compilers/pcc/pcc-libs-1.0.0/libpcc/ashldi3.c | 60 + compilers/pcc/pcc-libs-1.0.0/libpcc/ashrdi3.c | 72 + compilers/pcc/pcc-libs-1.0.0/libpcc/bitcnt.c | 50 + compilers/pcc/pcc-libs-1.0.0/libpcc/cmpdi2.c | 53 + compilers/pcc/pcc-libs-1.0.0/libpcc/divdi3.c | 61 + compilers/pcc/pcc-libs-1.0.0/libpcc/fixdfdi.c | 56 + compilers/pcc/pcc-libs-1.0.0/libpcc/fixsfdi.c | 56 + compilers/pcc/pcc-libs-1.0.0/libpcc/fixunsdfdi.c | 74 + compilers/pcc/pcc-libs-1.0.0/libpcc/fixunssfdi.c | 93 + compilers/pcc/pcc-libs-1.0.0/libpcc/floatdidf.c | 68 + compilers/pcc/pcc-libs-1.0.0/libpcc/floatdisf.c | 70 + compilers/pcc/pcc-libs-1.0.0/libpcc/floatunsdidf.c | 53 + .../pcc/pcc-libs-1.0.0/libpcc/include/CVS/Entries | 12 + .../pcc-libs-1.0.0/libpcc/include/CVS/Repository | 1 + .../pcc/pcc-libs-1.0.0/libpcc/include/CVS/Root | 1 + .../pcc/pcc-libs-1.0.0/libpcc/include/CVS/Tag | 1 + .../pcc/pcc-libs-1.0.0/libpcc/include/float.h | 1 + .../pcc/pcc-libs-1.0.0/libpcc/include/iso646.h | 18 + .../pcc-libs-1.0.0/libpcc/include/libpcc_float.h | 57 + .../pcc-libs-1.0.0/libpcc/include/libpcc_limits.h | 76 + .../pcc-libs-1.0.0/libpcc/include/libpcc_stdarg.h | 35 + .../pcc-libs-1.0.0/libpcc/include/libpcc_stdbool.h | 14 + .../pcc-libs-1.0.0/libpcc/include/libpcc_stddef.h | 75 + .../pcc/pcc-libs-1.0.0/libpcc/include/limits.h | 1 + .../pcc/pcc-libs-1.0.0/libpcc/include/stdarg.h | 1 + .../pcc/pcc-libs-1.0.0/libpcc/include/stdbool.h | 1 + .../pcc/pcc-libs-1.0.0/libpcc/include/stddef.h | 1 + compilers/pcc/pcc-libs-1.0.0/libpcc/iordi3.c | 52 + compilers/pcc/pcc-libs-1.0.0/libpcc/lshldi3.c | 60 + compilers/pcc/pcc-libs-1.0.0/libpcc/lshrdi3.c | 59 + compilers/pcc/pcc-libs-1.0.0/libpcc/moddi3.c | 61 + compilers/pcc/pcc-libs-1.0.0/libpcc/muldi3.c | 240 + compilers/pcc/pcc-libs-1.0.0/libpcc/negdi2.c | 51 + compilers/pcc/pcc-libs-1.0.0/libpcc/notdi2.c | 52 + compilers/pcc/pcc-libs-1.0.0/libpcc/qdivrem.c | 276 + compilers/pcc/pcc-libs-1.0.0/libpcc/quad.h | 157 + compilers/pcc/pcc-libs-1.0.0/libpcc/ssp.c | 71 + compilers/pcc/pcc-libs-1.0.0/libpcc/subdi3.c | 53 + compilers/pcc/pcc-libs-1.0.0/libpcc/ucmpdi2.c | 52 + compilers/pcc/pcc-libs-1.0.0/libpcc/udivdi3.c | 47 + compilers/pcc/pcc-libs-1.0.0/libpcc/umoddi3.c | 49 + compilers/pcc/pcc-libs-1.0.0/libpcc/xordi3.c | 52 + .../pcc/pcc-libs-1.0.0/libsoftfloat/CVS/Entries | 42 + .../pcc/pcc-libs-1.0.0/libsoftfloat/CVS/Repository | 1 + compilers/pcc/pcc-libs-1.0.0/libsoftfloat/CVS/Root | 1 + compilers/pcc/pcc-libs-1.0.0/libsoftfloat/CVS/Tag | 1 + .../pcc/pcc-libs-1.0.0/libsoftfloat/Makefile.in | 58 + .../pcc/pcc-libs-1.0.0/libsoftfloat/README.NetBSD | 8 + .../pcc/pcc-libs-1.0.0/libsoftfloat/README.txt | 39 + .../pcc-libs-1.0.0/libsoftfloat/arch/CVS/Entries | 8 + .../libsoftfloat/arch/CVS/Repository | 1 + .../pcc/pcc-libs-1.0.0/libsoftfloat/arch/CVS/Root | 1 + .../pcc/pcc-libs-1.0.0/libsoftfloat/arch/CVS/Tag | 1 + .../libsoftfloat/arch/amd64/CVS/Entries | 5 + .../libsoftfloat/arch/amd64/CVS/Repository | 1 + .../libsoftfloat/arch/amd64/CVS/Root | 1 + .../pcc-libs-1.0.0/libsoftfloat/arch/amd64/CVS/Tag | 1 + .../libsoftfloat/arch/amd64/ieeefp.h | 26 + .../libsoftfloat/arch/amd64/milieu.h | 48 + .../libsoftfloat/arch/amd64/softfloat.h | 303 + .../libsoftfloat/arch/amd64/x86_64-gcc.h | 83 + .../libsoftfloat/arch/arm/CVS/Entries | 4 + .../libsoftfloat/arch/arm/CVS/Repository | 1 + .../pcc-libs-1.0.0/libsoftfloat/arch/arm/CVS/Root | 1 + .../pcc-libs-1.0.0/libsoftfloat/arch/arm/CVS/Tag | 1 + .../pcc-libs-1.0.0/libsoftfloat/arch/arm/arm-gcc.h | 100 + .../pcc-libs-1.0.0/libsoftfloat/arch/arm/milieu.h | 48 + .../libsoftfloat/arch/arm/softfloat.h | 314 + .../libsoftfloat/arch/i386/CVS/Entries | 5 + .../libsoftfloat/arch/i386/CVS/Repository | 1 + .../pcc-libs-1.0.0/libsoftfloat/arch/i386/CVS/Root | 1 + .../pcc-libs-1.0.0/libsoftfloat/arch/i386/CVS/Tag | 1 + .../libsoftfloat/arch/i386/i386-gcc.h | 83 + .../pcc-libs-1.0.0/libsoftfloat/arch/i386/ieeefp.h | 26 + .../pcc-libs-1.0.0/libsoftfloat/arch/i386/milieu.h | 48 + .../libsoftfloat/arch/i386/softfloat.h | 303 + .../libsoftfloat/arch/m68k/CVS/Entries | 4 + .../libsoftfloat/arch/m68k/CVS/Repository | 1 + .../pcc-libs-1.0.0/libsoftfloat/arch/m68k/CVS/Root | 1 + .../pcc-libs-1.0.0/libsoftfloat/arch/m68k/CVS/Tag | 1 + .../libsoftfloat/arch/m68k/m68k-gcc.h | 89 + .../pcc-libs-1.0.0/libsoftfloat/arch/m68k/milieu.h | 48 + .../libsoftfloat/arch/m68k/softfloat.h | 302 + .../libsoftfloat/arch/powerpc/CVS/Entries | 5 + .../libsoftfloat/arch/powerpc/CVS/Repository | 1 + .../libsoftfloat/arch/powerpc/CVS/Root | 1 + .../libsoftfloat/arch/powerpc/CVS/Tag | 1 + .../libsoftfloat/arch/powerpc/ieeefp.h | 23 + .../libsoftfloat/arch/powerpc/milieu.h | 48 + .../libsoftfloat/arch/powerpc/powerpc-gcc.h | 89 + .../libsoftfloat/arch/powerpc/softfloat.h | 303 + .../libsoftfloat/arch/sh3/CVS/Entries | 4 + .../libsoftfloat/arch/sh3/CVS/Repository | 1 + .../pcc-libs-1.0.0/libsoftfloat/arch/sh3/CVS/Root | 1 + .../pcc-libs-1.0.0/libsoftfloat/arch/sh3/CVS/Tag | 1 + .../pcc-libs-1.0.0/libsoftfloat/arch/sh3/milieu.h | 48 + .../pcc-libs-1.0.0/libsoftfloat/arch/sh3/sh3-gcc.h | 89 + .../libsoftfloat/arch/sh3/softfloat.h | 314 + .../libsoftfloat/arch/sparc64/CVS/Entries | 6 + .../libsoftfloat/arch/sparc64/CVS/Repository | 1 + .../libsoftfloat/arch/sparc64/CVS/Root | 1 + .../libsoftfloat/arch/sparc64/CVS/Tag | 1 + .../libsoftfloat/arch/sparc64/ieeefp.h | 23 + .../libsoftfloat/arch/sparc64/milieu.h | 48 + .../libsoftfloat/arch/sparc64/softfloat-qp.h | 88 + .../libsoftfloat/arch/sparc64/softfloat.h | 303 + .../libsoftfloat/arch/sparc64/sparc64-gcc.h | 89 + .../pcc-libs-1.0.0/libsoftfloat/bits32/CVS/Entries | 3 + .../libsoftfloat/bits32/CVS/Repository | 1 + .../pcc-libs-1.0.0/libsoftfloat/bits32/CVS/Root | 1 + .../pcc/pcc-libs-1.0.0/libsoftfloat/bits32/CVS/Tag | 1 + .../libsoftfloat/bits32/softfloat-macros | 648 ++ .../pcc-libs-1.0.0/libsoftfloat/bits32/softfloat.c | 2349 ++++++++ .../pcc-libs-1.0.0/libsoftfloat/bits64/CVS/Entries | 3 + .../libsoftfloat/bits64/CVS/Repository | 1 + .../pcc-libs-1.0.0/libsoftfloat/bits64/CVS/Root | 1 + .../pcc/pcc-libs-1.0.0/libsoftfloat/bits64/CVS/Tag | 1 + .../libsoftfloat/bits64/softfloat-macros | 745 +++ .../pcc-libs-1.0.0/libsoftfloat/bits64/softfloat.c | 5547 +++++++++++++++++ compilers/pcc/pcc-libs-1.0.0/libsoftfloat/eqdf2.c | 19 + compilers/pcc/pcc-libs-1.0.0/libsoftfloat/eqsf2.c | 19 + .../pcc/pcc-libs-1.0.0/libsoftfloat/fpgetmask.c | 50 + .../pcc/pcc-libs-1.0.0/libsoftfloat/fpgetround.c | 50 + .../pcc/pcc-libs-1.0.0/libsoftfloat/fpgetsticky.c | 50 + .../pcc/pcc-libs-1.0.0/libsoftfloat/fpsetmask.c | 53 + .../pcc/pcc-libs-1.0.0/libsoftfloat/fpsetround.c | 53 + .../pcc/pcc-libs-1.0.0/libsoftfloat/fpsetsticky.c | 53 + compilers/pcc/pcc-libs-1.0.0/libsoftfloat/gedf2.c | 19 + compilers/pcc/pcc-libs-1.0.0/libsoftfloat/gesf2.c | 19 + compilers/pcc/pcc-libs-1.0.0/libsoftfloat/gexf2.c | 22 + compilers/pcc/pcc-libs-1.0.0/libsoftfloat/gtdf2.c | 19 + compilers/pcc/pcc-libs-1.0.0/libsoftfloat/gtsf2.c | 19 + compilers/pcc/pcc-libs-1.0.0/libsoftfloat/gtxf2.c | 22 + compilers/pcc/pcc-libs-1.0.0/libsoftfloat/ledf2.c | 19 + compilers/pcc/pcc-libs-1.0.0/libsoftfloat/lesf2.c | 19 + compilers/pcc/pcc-libs-1.0.0/libsoftfloat/ltdf2.c | 19 + compilers/pcc/pcc-libs-1.0.0/libsoftfloat/ltsf2.c | 19 + .../pcc/pcc-libs-1.0.0/libsoftfloat/namespace.h | 8 + compilers/pcc/pcc-libs-1.0.0/libsoftfloat/nedf2.c | 19 + compilers/pcc/pcc-libs-1.0.0/libsoftfloat/negdf2.c | 19 + compilers/pcc/pcc-libs-1.0.0/libsoftfloat/negsf2.c | 19 + compilers/pcc/pcc-libs-1.0.0/libsoftfloat/negxf2.c | 22 + compilers/pcc/pcc-libs-1.0.0/libsoftfloat/nesf2.c | 19 + compilers/pcc/pcc-libs-1.0.0/libsoftfloat/nexf2.c | 22 + .../libsoftfloat/softfloat-for-gcc.h | 58 + .../libsoftfloat/softfloat-history.txt | 52 + .../libsoftfloat/softfloat-source.txt | 383 ++ .../libsoftfloat/softfloat-specialize | 491 ++ .../pcc/pcc-libs-1.0.0/libsoftfloat/softfloat.txt | 372 ++ .../libsoftfloat/templates/CVS/Entries | 4 + .../libsoftfloat/templates/CVS/Repository | 1 + .../pcc-libs-1.0.0/libsoftfloat/templates/CVS/Root | 1 + .../pcc-libs-1.0.0/libsoftfloat/templates/CVS/Tag | 1 + .../pcc-libs-1.0.0/libsoftfloat/templates/milieu.h | 48 + .../libsoftfloat/templates/softfloat-specialize | 464 ++ .../libsoftfloat/templates/softfloat.h | 290 + .../pcc-libs-1.0.0/libsoftfloat/timesoftfloat.c | 2636 +++++++++ .../pcc-libs-1.0.0/libsoftfloat/timesoftfloat.txt | 149 + .../pcc/pcc-libs-1.0.0/libsoftfloat/unorddf2.c | 23 + .../pcc/pcc-libs-1.0.0/libsoftfloat/unordsf2.c | 23 + 731 files changed, 151256 insertions(+) create mode 100644 compilers/pcc/pcc-1.0.0/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/DATESTAMP create mode 100644 compilers/pcc/pcc-1.0.0/Makefile.in create mode 100644 compilers/pcc/pcc-1.0.0/arch/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/arch/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/arch/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/arch/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/arch/amd64/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/arch/amd64/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/arch/amd64/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/arch/amd64/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/arch/amd64/code.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/amd64/local.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/amd64/local2.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/amd64/macdefs.h create mode 100644 compilers/pcc/pcc-1.0.0/arch/amd64/order.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/amd64/table.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/arm/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/arch/arm/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/arch/arm/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/arch/arm/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/arch/arm/code.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/arm/local.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/arm/local2.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/arm/macdefs.h create mode 100644 compilers/pcc/pcc-1.0.0/arch/arm/order.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/arm/table.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/hppa/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/arch/hppa/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/arch/hppa/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/arch/hppa/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/arch/hppa/code.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/hppa/local.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/hppa/local2.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/hppa/macdefs.h create mode 100644 compilers/pcc/pcc-1.0.0/arch/hppa/order.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/hppa/table.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/i386/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/arch/i386/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/arch/i386/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/arch/i386/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/arch/i386/code.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/i386/flocal.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/i386/local.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/i386/local2.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/i386/macdefs.h create mode 100644 compilers/pcc/pcc-1.0.0/arch/i386/order.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/i386/table.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/m16c/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/arch/m16c/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/arch/m16c/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/arch/m16c/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/arch/m16c/TODO create mode 100644 compilers/pcc/pcc-1.0.0/arch/m16c/code.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/m16c/local.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/m16c/local2.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/m16c/macdefs.h create mode 100644 compilers/pcc/pcc-1.0.0/arch/m16c/order.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/m16c/table.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/mips/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/arch/mips/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/arch/mips/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/arch/mips/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/arch/mips/TODO create mode 100644 compilers/pcc/pcc-1.0.0/arch/mips/code.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/mips/local.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/mips/local2.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/mips/macdefs.h create mode 100644 compilers/pcc/pcc-1.0.0/arch/mips/order.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/mips/table.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/nova/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/arch/nova/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/arch/nova/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/arch/nova/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/arch/nova/README create mode 100644 compilers/pcc/pcc-1.0.0/arch/nova/code.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/nova/local.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/nova/local2.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/nova/macdefs.h create mode 100644 compilers/pcc/pcc-1.0.0/arch/nova/order.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/nova/table.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/pdp10/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/arch/pdp10/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/arch/pdp10/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/arch/pdp10/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/arch/pdp10/README create mode 100644 compilers/pcc/pcc-1.0.0/arch/pdp10/code.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/pdp10/local.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/pdp10/local2.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/pdp10/macdefs.h create mode 100644 compilers/pcc/pcc-1.0.0/arch/pdp10/order.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/pdp10/table.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/pdp11/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/arch/pdp11/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/arch/pdp11/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/arch/pdp11/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/arch/pdp11/code.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/pdp11/local.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/pdp11/local2.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/pdp11/macdefs.h create mode 100644 compilers/pcc/pcc-1.0.0/arch/pdp11/order.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/pdp11/table.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/powerpc/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/arch/powerpc/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/arch/powerpc/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/arch/powerpc/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/arch/powerpc/README create mode 100644 compilers/pcc/pcc-1.0.0/arch/powerpc/code.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/powerpc/local.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/powerpc/local2.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/powerpc/macdefs.h create mode 100644 compilers/pcc/pcc-1.0.0/arch/powerpc/order.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/powerpc/table.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/sparc64/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/arch/sparc64/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/arch/sparc64/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/arch/sparc64/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/arch/sparc64/code.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/sparc64/local.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/sparc64/local2.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/sparc64/macdefs.h create mode 100644 compilers/pcc/pcc-1.0.0/arch/sparc64/order.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/sparc64/table.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/vax/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/arch/vax/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/arch/vax/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/arch/vax/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/arch/vax/code.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/vax/local.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/vax/local2.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/vax/macdefs.h create mode 100644 compilers/pcc/pcc-1.0.0/arch/vax/order.c create mode 100644 compilers/pcc/pcc-1.0.0/arch/vax/table.c create mode 100644 compilers/pcc/pcc-1.0.0/cc/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/cc/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/cc/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/cc/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/cc/Makefile.in create mode 100644 compilers/pcc/pcc-1.0.0/cc/cc/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/cc/cc/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/cc/cc/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/cc/cc/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/cc/cc/Makefile.in create mode 100644 compilers/pcc/pcc-1.0.0/cc/cc/cc.1 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cc/cc.c create mode 100644 compilers/pcc/pcc-1.0.0/cc/ccom/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/cc/ccom/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/cc/ccom/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/cc/ccom/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/cc/ccom/Makefile.in create mode 100644 compilers/pcc/pcc-1.0.0/cc/ccom/builtins.c create mode 100644 compilers/pcc/pcc-1.0.0/cc/ccom/ccom.1 create mode 100644 compilers/pcc/pcc-1.0.0/cc/ccom/cgram.y create mode 100644 compilers/pcc/pcc-1.0.0/cc/ccom/gcc_compat.c create mode 100644 compilers/pcc/pcc-1.0.0/cc/ccom/init.c create mode 100644 compilers/pcc/pcc-1.0.0/cc/ccom/inline.c create mode 100644 compilers/pcc/pcc-1.0.0/cc/ccom/main.c create mode 100644 compilers/pcc/pcc-1.0.0/cc/ccom/optim.c create mode 100644 compilers/pcc/pcc-1.0.0/cc/ccom/pass1.h create mode 100644 compilers/pcc/pcc-1.0.0/cc/ccom/pftn.c create mode 100644 compilers/pcc/pcc-1.0.0/cc/ccom/scan.l create mode 100644 compilers/pcc/pcc-1.0.0/cc/ccom/softfloat.c create mode 100644 compilers/pcc/pcc-1.0.0/cc/ccom/stabs.c create mode 100644 compilers/pcc/pcc-1.0.0/cc/ccom/symtabs.c create mode 100644 compilers/pcc/pcc-1.0.0/cc/ccom/trees.c create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/Makefile.in create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/cpp.1 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/cpp.c create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/cpp.h create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/cpy.y create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/scanner.l create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/res1 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/res10 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/res11 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/res12 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/res13 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/res2 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/res3 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/res4 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/res5 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/res6 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/res7 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/res8 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/res9 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/test1 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/test10 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/test11 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/test12 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/test13 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/test2 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/test3 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/test4 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/test5 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/test6 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/test7 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/test8 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/tests/test9 create mode 100644 compilers/pcc/pcc-1.0.0/cc/cpp/token.c create mode 100644 compilers/pcc/pcc-1.0.0/config.guess create mode 100644 compilers/pcc/pcc-1.0.0/config.h.in create mode 100644 compilers/pcc/pcc-1.0.0/config.sub create mode 100755 compilers/pcc/pcc-1.0.0/configure create mode 100644 compilers/pcc/pcc-1.0.0/configure.ac create mode 100644 compilers/pcc/pcc-1.0.0/f77/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/f77/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/f77/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/f77/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/f77/Makefile.in create mode 100644 compilers/pcc/pcc-1.0.0/f77/f77/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/f77/f77/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/f77/f77/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/f77/f77/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/f77/f77/Makefile.in create mode 100644 compilers/pcc/pcc-1.0.0/f77/f77/f77.1 create mode 100644 compilers/pcc/pcc-1.0.0/f77/f77/f77.c create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/Makefile.in create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/data.c create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/defines.h create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/defs.h create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/equiv.c create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/error.c create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/exec.c create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/expr.c create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/ftypes.h create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/gram.dcl create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/gram.exec create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/gram.expr create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/gram.head create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/gram.io create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/init.c create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/intr.c create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/io.c create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/lex.c create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/main.c create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/misc.c create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/proc.c create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/put.c create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/putscj.c create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/scjdefs.h create mode 100644 compilers/pcc/pcc-1.0.0/f77/fcom/tokens create mode 100755 compilers/pcc/pcc-1.0.0/install-sh create mode 100644 compilers/pcc/pcc-1.0.0/mip/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/mip/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/mip/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/mip/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/mip/common.c create mode 100644 compilers/pcc/pcc-1.0.0/mip/compat.c create mode 100644 compilers/pcc/pcc-1.0.0/mip/compat.h create mode 100644 compilers/pcc/pcc-1.0.0/mip/manifest.h create mode 100644 compilers/pcc/pcc-1.0.0/mip/match.c create mode 100644 compilers/pcc/pcc-1.0.0/mip/mkext.c create mode 100644 compilers/pcc/pcc-1.0.0/mip/node.h create mode 100644 compilers/pcc/pcc-1.0.0/mip/optim2.c create mode 100644 compilers/pcc/pcc-1.0.0/mip/pass2.h create mode 100644 compilers/pcc/pcc-1.0.0/mip/reader.c create mode 100644 compilers/pcc/pcc-1.0.0/mip/regs.c create mode 100644 compilers/pcc/pcc-1.0.0/os/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/os/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/os/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/os/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/os/bsd/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/os/bsd/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/os/bsd/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/os/bsd/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/os/bsd/ccconfig.h create mode 100644 compilers/pcc/pcc-1.0.0/os/darwin/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/os/darwin/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/os/darwin/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/os/darwin/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/os/darwin/ccconfig.h create mode 100644 compilers/pcc/pcc-1.0.0/os/dragonfly/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/os/dragonfly/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/os/dragonfly/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/os/dragonfly/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/os/dragonfly/ccconfig.h create mode 100644 compilers/pcc/pcc-1.0.0/os/freebsd/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/os/freebsd/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/os/freebsd/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/os/freebsd/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/os/freebsd/ccconfig.h create mode 100644 compilers/pcc/pcc-1.0.0/os/linux/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/os/linux/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/os/linux/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/os/linux/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/os/linux/ccconfig.h create mode 100644 compilers/pcc/pcc-1.0.0/os/midnightbsd/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/os/midnightbsd/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/os/midnightbsd/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/os/midnightbsd/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/os/midnightbsd/ccconfig.h create mode 100644 compilers/pcc/pcc-1.0.0/os/mirbsd/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/os/mirbsd/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/os/mirbsd/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/os/mirbsd/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/os/mirbsd/ccconfig.h create mode 100644 compilers/pcc/pcc-1.0.0/os/netbsd/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/os/netbsd/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/os/netbsd/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/os/netbsd/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/os/netbsd/ccconfig.h create mode 100644 compilers/pcc/pcc-1.0.0/os/nextstep/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/os/nextstep/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/os/nextstep/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/os/nextstep/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/os/nextstep/ccconfig.h create mode 100644 compilers/pcc/pcc-1.0.0/os/none/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/os/none/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/os/none/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/os/none/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/os/none/ccconfig.h create mode 100644 compilers/pcc/pcc-1.0.0/os/openbsd/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/os/openbsd/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/os/openbsd/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/os/openbsd/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/os/openbsd/ccconfig.h create mode 100644 compilers/pcc/pcc-1.0.0/os/openbsd/f77config.h create mode 100644 compilers/pcc/pcc-1.0.0/os/sunos/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/os/sunos/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/os/sunos/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/os/sunos/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/os/sunos/ccconfig.h create mode 100644 compilers/pcc/pcc-1.0.0/os/win32/CVS/Entries create mode 100644 compilers/pcc/pcc-1.0.0/os/win32/CVS/Repository create mode 100644 compilers/pcc/pcc-1.0.0/os/win32/CVS/Root create mode 100644 compilers/pcc/pcc-1.0.0/os/win32/CVS/Tag create mode 100644 compilers/pcc/pcc-1.0.0/os/win32/build.bat create mode 100755 compilers/pcc/pcc-1.0.0/os/win32/build_installer.bat create mode 100644 compilers/pcc/pcc-1.0.0/os/win32/ccconfig.h create mode 100644 compilers/pcc/pcc-1.0.0/os/win32/config.h create mode 100644 compilers/pcc/pcc-1.0.0/os/win32/pcc.iss create mode 100644 compilers/pcc/pcc-libs-1.0.0/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/CVS/Tag create mode 100644 compilers/pcc/pcc-libs-1.0.0/Makefile.in create mode 100644 compilers/pcc/pcc-libs-1.0.0/config.guess create mode 100644 compilers/pcc/pcc-libs-1.0.0/config.sub create mode 100755 compilers/pcc/pcc-libs-1.0.0/configure create mode 100644 compilers/pcc/pcc-libs-1.0.0/configure.ac create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/CVS/Tag create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/Makefile.in create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/README create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/darwin/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/darwin/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/darwin/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/darwin/CVS/Tag create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/darwin/Makefile create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/darwin/common.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/darwin/common.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/darwin/i386/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/darwin/i386/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/darwin/i386/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/darwin/i386/CVS/Tag create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/darwin/i386/crt0.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/darwin/i386/dylib1.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/darwin/macho.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/darwin/powerpc/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/darwin/powerpc/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/darwin/powerpc/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/darwin/powerpc/CVS/Tag create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/darwin/powerpc/crt0.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/darwin/powerpc/dylib1.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/linux/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/linux/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/linux/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/linux/CVS/Tag create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/linux/Makefile create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/linux/amd64/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/linux/amd64/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/linux/amd64/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/linux/amd64/CVS/Tag create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/linux/amd64/crt0.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/linux/amd64/crti.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/linux/amd64/crtn.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/linux/common.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/linux/common.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/linux/crtbegin.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/linux/crtend.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/linux/i386/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/linux/i386/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/linux/i386/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/linux/i386/CVS/Tag create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/linux/i386/crt0.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/linux/i386/crti.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/linux/i386/crtn.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/netbsd/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/netbsd/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/netbsd/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/netbsd/CVS/Tag create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/netbsd/Makefile create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/netbsd/common.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/netbsd/crtbegin.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/csu/netbsd/crtend.c create mode 100755 compilers/pcc/pcc-libs-1.0.0/install-sh create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/CVS/Tag create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/Makefile create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/abort_.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/c_abs.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/c_cos.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/c_div.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/c_exp.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/c_log.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/c_sin.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/c_sqrt.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/cabs.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/complex create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_abs.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_acos.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_asin.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_atan.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_atn2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_cnjg.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_cos.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_cosh.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_dim.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_erf.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_erfc.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_exp.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_imag.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_int.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_lg10.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_log.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_mod.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_nint.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_prod.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_sign.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_sin.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_sinh.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_sqrt.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_tan.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/d_tanh.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/erf.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/f77lib.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/getarg_.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/h_abs.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/h_dim.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/h_dnnt.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/h_indx.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/h_len.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/h_mod.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/h_nint.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/h_sign.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/hl_ge.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/hl_gt.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/hl_le.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/hl_lt.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/i_abs.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/i_dim.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/i_dnnt.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/i_indx.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/i_len.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/i_mod.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/i_nint.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/i_sign.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/iargc_.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/l_ge.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/l_gt.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/l_le.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/l_lt.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/main.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/pow_ci.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/pow_dd.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/pow_di.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/pow_hh.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/pow_ii.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/pow_ri.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/pow_zi.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/pow_zz.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/r_abs.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/r_acos.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/r_asin.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/r_atan.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/r_atn2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/r_cnjg.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/r_cos.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/r_cosh.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/r_dim.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/r_erf.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/r_erfc.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/r_exp.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/r_imag.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/r_int.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/r_lg10.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/r_log.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/r_mod.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/r_nint.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/r_sign.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/r_sin.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/r_sinh.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/r_sqrt.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/r_tan.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/r_tanh.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/s_cat.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/s_cmp.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/s_copy.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/s_paus.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/s_rnge.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/s_stop.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/signal_.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/sinh.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/tanh.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/z_abs.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/z_cos.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/z_div.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/z_exp.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/z_log.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/z_sin.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libF77/z_sqrt.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/CVS/Tag create mode 100755 compilers/pcc/pcc-libs-1.0.0/libI77/Makefile create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/backspace.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/close.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/dfe.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/due.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/endfile.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/err.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/fio.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/fmt.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/fmt.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/fmtlib.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/iio.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/inquire.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/lib.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/lio.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/lio.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/lread.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/open.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/pwd.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/rdfmt.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/rewind.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/rsfe.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/sfe.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/sue.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/uio.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/util.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/wrtfmt.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libI77/wsfe.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/CVS/Tag create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/Makefile.in create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/_alloca.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/_ftol.asm create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/_ftol.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/adddi3.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/anddi3.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/ashldi3.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/ashrdi3.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/bitcnt.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/cmpdi2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/divdi3.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/fixdfdi.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/fixsfdi.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/fixunsdfdi.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/fixunssfdi.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/floatdidf.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/floatdisf.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/floatunsdidf.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/include/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/include/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/include/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/include/CVS/Tag create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/include/float.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/include/iso646.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/include/libpcc_float.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/include/libpcc_limits.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/include/libpcc_stdarg.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/include/libpcc_stdbool.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/include/libpcc_stddef.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/include/limits.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/include/stdarg.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/include/stdbool.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/include/stddef.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/iordi3.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/lshldi3.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/lshrdi3.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/moddi3.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/muldi3.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/negdi2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/notdi2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/qdivrem.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/quad.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/ssp.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/subdi3.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/ucmpdi2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/udivdi3.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/umoddi3.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libpcc/xordi3.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/CVS/Tag create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/Makefile.in create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/README.NetBSD create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/README.txt create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/CVS/Tag create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/amd64/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/amd64/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/amd64/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/amd64/CVS/Tag create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/amd64/ieeefp.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/amd64/milieu.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/amd64/softfloat.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/amd64/x86_64-gcc.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/arm/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/arm/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/arm/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/arm/CVS/Tag create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/arm/arm-gcc.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/arm/milieu.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/arm/softfloat.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/i386/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/i386/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/i386/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/i386/CVS/Tag create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/i386/i386-gcc.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/i386/ieeefp.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/i386/milieu.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/i386/softfloat.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/m68k/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/m68k/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/m68k/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/m68k/CVS/Tag create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/m68k/m68k-gcc.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/m68k/milieu.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/m68k/softfloat.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/powerpc/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/powerpc/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/powerpc/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/powerpc/CVS/Tag create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/powerpc/ieeefp.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/powerpc/milieu.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/powerpc/powerpc-gcc.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/powerpc/softfloat.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/sh3/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/sh3/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/sh3/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/sh3/CVS/Tag create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/sh3/milieu.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/sh3/sh3-gcc.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/sh3/softfloat.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/sparc64/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/sparc64/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/sparc64/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/sparc64/CVS/Tag create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/sparc64/ieeefp.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/sparc64/milieu.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/sparc64/softfloat-qp.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/sparc64/softfloat.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/arch/sparc64/sparc64-gcc.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/bits32/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/bits32/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/bits32/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/bits32/CVS/Tag create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/bits32/softfloat-macros create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/bits32/softfloat.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/bits64/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/bits64/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/bits64/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/bits64/CVS/Tag create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/bits64/softfloat-macros create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/bits64/softfloat.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/eqdf2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/eqsf2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/fpgetmask.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/fpgetround.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/fpgetsticky.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/fpsetmask.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/fpsetround.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/fpsetsticky.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/gedf2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/gesf2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/gexf2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/gtdf2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/gtsf2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/gtxf2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/ledf2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/lesf2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/ltdf2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/ltsf2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/namespace.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/nedf2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/negdf2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/negsf2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/negxf2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/nesf2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/nexf2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/softfloat-for-gcc.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/softfloat-history.txt create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/softfloat-source.txt create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/softfloat-specialize create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/softfloat.txt create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/templates/CVS/Entries create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/templates/CVS/Repository create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/templates/CVS/Root create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/templates/CVS/Tag create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/templates/milieu.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/templates/softfloat-specialize create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/templates/softfloat.h create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/timesoftfloat.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/timesoftfloat.txt create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/unorddf2.c create mode 100644 compilers/pcc/pcc-libs-1.0.0/libsoftfloat/unordsf2.c diff --git a/compilers/pcc/pcc-1.0.0/CVS/Entries b/compilers/pcc/pcc-1.0.0/CVS/Entries new file mode 100644 index 00000000..329953ee --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/CVS/Entries @@ -0,0 +1,14 @@ +/DATESTAMP/1.42/Mon Feb 21 02:00:02 2011//Tr-1-0-0-RELEASE +/Makefile.in/1.6/Fri Jul 18 14:00:38 2008//Tr-1-0-0-RELEASE +/config.guess/1.3/Sun Sep 16 08:01:04 2007//Tr-1-0-0-RELEASE +/config.h.in/1.23/Sat May 16 07:25:55 2009//Tr-1-0-0-RELEASE +/config.sub/1.6/Tue Jul 15 17:33:57 2008//Tr-1-0-0-RELEASE +/configure/1.77.2.3/Fri Apr 1 13:58:31 2011//Tr-1-0-0-RELEASE +/configure.ac/1.92.2.3/Fri Apr 1 13:58:31 2011//Tr-1-0-0-RELEASE +/install-sh/1.1/Sat Oct 16 07:57:40 2004//Tr-1-0-0-RELEASE +D/arch//// +D/cc//// +D/f77//// +D/mip//// +D/os//// +D diff --git a/compilers/pcc/pcc-1.0.0/CVS/Repository b/compilers/pcc/pcc-1.0.0/CVS/Repository new file mode 100644 index 00000000..ea7cb06c --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/CVS/Repository @@ -0,0 +1 @@ +pcc diff --git a/compilers/pcc/pcc-1.0.0/CVS/Root b/compilers/pcc/pcc-1.0.0/CVS/Root new file mode 100644 index 00000000..71e2ccb9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/CVS/Root @@ -0,0 +1 @@ +/cvsroot diff --git a/compilers/pcc/pcc-1.0.0/CVS/Tag b/compilers/pcc/pcc-1.0.0/CVS/Tag new file mode 100644 index 00000000..060fac05 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/CVS/Tag @@ -0,0 +1 @@ +Nr-1-0-0-RELEASE diff --git a/compilers/pcc/pcc-1.0.0/DATESTAMP b/compilers/pcc/pcc-1.0.0/DATESTAMP new file mode 100644 index 00000000..97840598 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/DATESTAMP @@ -0,0 +1 @@ +20110221 diff --git a/compilers/pcc/pcc-1.0.0/Makefile.in b/compilers/pcc/pcc-1.0.0/Makefile.in new file mode 100644 index 00000000..296e52ca --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/Makefile.in @@ -0,0 +1,34 @@ +# $Id: Makefile.in,v 1.6 2008/07/18 14:00:38 gmcgarry Exp $ +# +# Makefile.in for top-level of pcc. +# + +@SET_MAKE@ +VPATH=@srcdir@ +CC=@CC@ +CFLAGS=@CFLAGS@ @ADD_CFLAGS@ +LDFLAGS=@LDFLAGS@ +CPPFLAGS=@CPPFLAGS@ +YACC=@YACC@ +LEX=@LEX@ + +SUBDIR=cc + +all: ${SUBDIR} + +install: + cd cc && ${MAKE} install + +clean: + cd cc && ${MAKE} clean + +distclean: + cd cc && ${MAKE} distclean + cd f77 && ${MAKE} distclean + /bin/rm -rf Makefile config.log stamp-h1 config.status \ + configure.lineno config.h autom4te.cache + +${SUBDIR}: nonexistant + cd $@ && $(MAKE) all $(MFLAGS) + +nonexistant: diff --git a/compilers/pcc/pcc-1.0.0/arch/CVS/Entries b/compilers/pcc/pcc-1.0.0/arch/CVS/Entries new file mode 100644 index 00000000..e4fe105e --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/CVS/Entries @@ -0,0 +1,13 @@ +D/amd64//// +D/arm//// +D/hppa//// +D/i386//// +D/m16c//// +D/mips//// +D/nova//// +D/pdp10//// +D/pdp11//// +D/powerpc//// +D/sparc64//// +D/vax//// +D diff --git a/compilers/pcc/pcc-1.0.0/arch/CVS/Repository b/compilers/pcc/pcc-1.0.0/arch/CVS/Repository new file mode 100644 index 00000000..1ee7dcf9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/CVS/Repository @@ -0,0 +1 @@ +pcc/arch diff --git a/compilers/pcc/pcc-1.0.0/arch/CVS/Root b/compilers/pcc/pcc-1.0.0/arch/CVS/Root new file mode 100644 index 00000000..71e2ccb9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/CVS/Root @@ -0,0 +1 @@ +/cvsroot diff --git a/compilers/pcc/pcc-1.0.0/arch/CVS/Tag b/compilers/pcc/pcc-1.0.0/arch/CVS/Tag new file mode 100644 index 00000000..6d489e3c --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/CVS/Tag @@ -0,0 +1 @@ +Tr-1-0-0-RELEASE diff --git a/compilers/pcc/pcc-1.0.0/arch/amd64/CVS/Entries b/compilers/pcc/pcc-1.0.0/arch/amd64/CVS/Entries new file mode 100644 index 00000000..464961a9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/amd64/CVS/Entries @@ -0,0 +1,7 @@ +/code.c/1.49/Sat Jan 29 14:55:33 2011//Tr-1-0-0-RELEASE +/local.c/1.41.2.2/Wed Mar 2 17:40:07 2011//Tr-1-0-0-RELEASE +/local2.c/1.41/Fri Feb 18 16:52:37 2011//Tr-1-0-0-RELEASE +/macdefs.h/1.17/Fri Feb 18 17:16:57 2011//Tr-1-0-0-RELEASE +/order.c/1.14/Fri Feb 18 17:08:31 2011//Tr-1-0-0-RELEASE +/table.c/1.45/Fri Feb 18 17:08:31 2011//Tr-1-0-0-RELEASE +D diff --git a/compilers/pcc/pcc-1.0.0/arch/amd64/CVS/Repository b/compilers/pcc/pcc-1.0.0/arch/amd64/CVS/Repository new file mode 100644 index 00000000..f491ec7a --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/amd64/CVS/Repository @@ -0,0 +1 @@ +pcc/arch/amd64 diff --git a/compilers/pcc/pcc-1.0.0/arch/amd64/CVS/Root b/compilers/pcc/pcc-1.0.0/arch/amd64/CVS/Root new file mode 100644 index 00000000..71e2ccb9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/amd64/CVS/Root @@ -0,0 +1 @@ +/cvsroot diff --git a/compilers/pcc/pcc-1.0.0/arch/amd64/CVS/Tag b/compilers/pcc/pcc-1.0.0/arch/amd64/CVS/Tag new file mode 100644 index 00000000..060fac05 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/amd64/CVS/Tag @@ -0,0 +1 @@ +Nr-1-0-0-RELEASE diff --git a/compilers/pcc/pcc-1.0.0/arch/amd64/code.c b/compilers/pcc/pcc-1.0.0/arch/amd64/code.c new file mode 100644 index 00000000..6fe11b8a --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/amd64/code.c @@ -0,0 +1,973 @@ +/* $Id: code.c,v 1.49 2011/01/29 14:55:33 ragge Exp $ */ +/* + * Copyright (c) 2008 Michael Shalayeff + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass1.h" + +static int nsse, ngpr, nrsp, rsaoff; +static int thissse, thisgpr, thisrsp; +enum { INTEGER = 1, INTMEM, SSE, SSEMEM, X87, STRREG, STRMEM, STRCPX }; +static const int argregsi[] = { RDI, RSI, RDX, RCX, R08, R09 }; +/* + * The Register Save Area looks something like this. + * It is put first on stack with fixed offsets. + * struct { + * long regs[6]; + * double xmm[8][2]; // 16 byte in width + * }; + */ +#define RSASZ (6*SZLONG+8*2*SZDOUBLE) +#define RSALONGOFF(x) (RSASZ-(x)*SZLONG) +#define RSADBLOFF(x) ((8*2*SZDOUBLE)-(x)*SZDOUBLE*2) +/* va_list */ +#define VAARGSZ (SZINT*2+SZPOINT(CHAR)*2) +#define VAGPOFF(x) (x) +#define VAFPOFF(x) (x-SZINT) +#define VAOFA(x) (x-SZINT-SZINT) +#define VARSA(x) (x-SZINT-SZINT-SZPOINT(0)) + +int lastloc = -1; +static int stroffset; + +static int varneeds; +#define NEED_GPNEXT 001 +#define NEED_FPNEXT 002 +#define NEED_1REGREF 004 +#define NEED_2REGREF 010 +#define NEED_MEMREF 020 + +static int argtyp(TWORD t, union dimfun *df, struct attr *ap); +static NODE *movtomem(NODE *p, int off, int reg); +static NODE *movtoreg(NODE *p, int rno); +void varattrib(char *name, struct attr *sap); + +/* + * Define everything needed to print out some data (or text). + * This means segment, alignment, visibility, etc. + */ +void +defloc(struct symtab *sp) +{ + extern char *nextsect; + static char *loctbl[] = { "text", "data", "section .rodata" }; + extern int tbss; + char *name; + TWORD t; + int s; + + if (sp == NULL) { + lastloc = -1; + return; + } + if (kflag) { +#ifdef MACHOABI + loctbl[DATA] = "section .data.rel.rw,\"aw\""; + loctbl[RDATA] = "section .data.rel.ro,\"aw\""; +#else + loctbl[DATA] = "section .data.rel.rw,\"aw\",@progbits"; + loctbl[RDATA] = "section .data.rel.ro,\"aw\",@progbits"; +#endif + } + t = sp->stype; + s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA; + if ((name = sp->soname) == NULL) + name = exname(sp->sname); + + if (sp->sflags & STLS) { + if (s != DATA) + cerror("non-data symbol in tls section"); + if (tbss) + nextsect = ".tbss,\"awT\",@nobits"; + else + nextsect = ".tdata,\"awT\",@progbits"; + tbss = 0; + lastloc = -1; + } + + varattrib(name, sp->sap); + + if (nextsect) { + printf(" .section %s\n", nextsect); + nextsect = NULL; + s = -1; + } else if (s != lastloc) + printf(" .%s\n", loctbl[s]); + lastloc = s; + while (ISARY(t)) + t = DECREF(t); + s = ISFTN(t) ? ALINT : talign(t, sp->sap); + if (s > ALCHAR) + printf(" .align %d\n", s/ALCHAR); + if (sp->sclass == EXTDEF) { + printf("\t.globl %s\n", name); +#ifndef MACHOABI + printf("\t.type %s,@%s\n", name, + ISFTN(t)? "function" : "object"); +#endif + } + if (sp->slevel == 0) + printf("%s:\n", name); + else + printf(LABFMT ":\n", sp->soffset); +} + +/* + * Print out variable attributes. + */ +void +varattrib(char *name, struct attr *sap) +{ + extern char *nextsect; + struct attr *ga; + + if ((ga = attr_find(sap, GCC_ATYP_SECTION)) != NULL) + nextsect = ga->sarg(0); + if ((ga = attr_find(sap, GCC_ATYP_WEAK)) != NULL) + printf(" .weak %s\n", name); + if (attr_find(sap, GCC_ATYP_DESTRUCTOR)) { + printf("\t.section\t.dtors,\"aw\",@progbits\n"); + printf("\t.align 8\n\t.quad\t%s\n", name); + lastloc = -1; + } + if (attr_find(sap, GCC_ATYP_CONSTRUCTOR)) { + printf("\t.section\t.ctors,\"aw\",@progbits\n"); + printf("\t.align 8\n\t.quad\t%s\n", name); + lastloc = -1; + } + if ((ga = attr_find(sap, GCC_ATYP_VISIBILITY)) && + strcmp(ga->sarg(0), "default")) + printf("\t.%s %s\n", ga->sarg(0), name); + if ((ga = attr_find(sap, GCC_ATYP_ALIASWEAK))) { + printf(" .weak %s\n", ga->sarg(0)); + printf(" .set %s,%s\n", ga->sarg(0), name); + } +} + +/* + * code for the end of a function + * deals with struct return here + * The return value is in (or pointed to by) RETREG. + */ +void +efcode() +{ + struct symtab *sp; + extern int gotnr; + TWORD t; + NODE *p, *r, *l; + int typ, ssz, rno; + + gotnr = 0; /* new number for next fun */ + sp = cftnsp; + t = DECREF(sp->stype); + if (t != STRTY && t != UNIONTY) + return; + + /* XXX should have one routine for this */ + if ((typ = argtyp(t, sp->sdf, sp->sap)) == STRREG || typ == STRCPX) { + /* Cast to long pointer and move to the registers */ + /* XXX can overrun struct size */ + /* XXX check carefully for SSE members */ + + if ((ssz = tsize(t, sp->sdf, sp->sap)) > SZLONG*2) + cerror("efcode1"); + + if (typ == STRCPX) { + t = DOUBLE; + rno = XMM0; + } else { + t = LONG; + rno = RAX; + } + if (ssz > SZLONG) { + p = block(REG, NIL, NIL, INCREF(t), 0, MKAP(t)); + regno(p) = RAX; + p = buildtree(UMUL, buildtree(PLUS, p, bcon(1)), NIL); + ecomp(movtoreg(p, rno+1)); + } + p = block(REG, NIL, NIL, INCREF(t), 0, MKAP(t)); + regno(p) = RAX; + p = buildtree(UMUL, p, NIL); + ecomp(movtoreg(p, rno)); + } else if (typ == STRMEM) { + r = block(REG, NIL, NIL, INCREF(t), sp->sdf, sp->sap); + regno(r) = RAX; + r = buildtree(UMUL, r, NIL); + l = tempnode(stroffset, INCREF(t), sp->sdf, sp->sap); + l = buildtree(UMUL, l, NIL); + ecomp(buildtree(ASSIGN, l, r)); + l = block(REG, NIL, NIL, LONG, 0, MKAP(LONG)); + regno(l) = RAX; + r = tempnode(stroffset, LONG, 0, MKAP(LONG)); + ecomp(buildtree(ASSIGN, l, r)); + } else + cerror("efcode"); +} + +/* + * code for the beginning of a function; a is an array of + * indices in symtab for the arguments; n is the number + */ +void +bfcode(struct symtab **s, int cnt) +{ + union arglist *al; + struct symtab *sp; + NODE *p, *r; + TWORD t; + int i, rno, typ; + + /* recalculate the arg offset and create TEMP moves */ + /* Always do this for reg, even if not optimizing, to free arg regs */ + nsse = ngpr = 0; + nrsp = ARGINIT; + if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) { + sp = cftnsp; + if (argtyp(DECREF(sp->stype), sp->sdf, sp->sap) == STRMEM) { + r = block(REG, NIL, NIL, LONG, 0, MKAP(LONG)); + regno(r) = argregsi[ngpr++]; + p = tempnode(0, r->n_type, r->n_df, r->n_ap); + stroffset = regno(p); + ecomp(buildtree(ASSIGN, p, r)); + } + } + + for (i = 0; i < cnt; i++) { + sp = s[i]; + + if (sp == NULL) + continue; /* XXX when happens this? */ + + switch (typ = argtyp(sp->stype, sp->sdf, sp->sap)) { + case INTEGER: + case SSE: + if (typ == SSE) + rno = XMM0 + nsse++; + else + rno = argregsi[ngpr++]; + r = block(REG, NIL, NIL, sp->stype, sp->sdf, sp->sap); + regno(r) = rno; + p = tempnode(0, sp->stype, sp->sdf, sp->sap); + sp->soffset = regno(p); + sp->sflags |= STNODE; + ecomp(buildtree(ASSIGN, p, r)); + break; + + case SSEMEM: + sp->soffset = nrsp; + nrsp += SZDOUBLE; + if (xtemps) { + p = tempnode(0, sp->stype, sp->sdf, sp->sap); + p = buildtree(ASSIGN, p, nametree(sp)); + sp->soffset = regno(p->n_left); + sp->sflags |= STNODE; + ecomp(p); + } + break; + + case INTMEM: + sp->soffset = nrsp; + nrsp += SZLONG; + if (xtemps) { + p = tempnode(0, sp->stype, sp->sdf, sp->sap); + p = buildtree(ASSIGN, p, nametree(sp)); + sp->soffset = regno(p->n_left); + sp->sflags |= STNODE; + ecomp(p); + } + break; + + case STRMEM: /* Struct in memory */ + sp->soffset = nrsp; + nrsp += tsize(sp->stype, sp->sdf, sp->sap); + break; + + case X87: /* long double args */ + sp->soffset = nrsp; + nrsp += SZLDOUBLE; + break; + + case STRCPX: + case STRREG: /* Struct in register */ + /* Allocate space on stack for the struct */ + /* For simplicity always fetch two longwords */ + autooff += (2*SZLONG); + + if (typ == STRCPX) { + t = DOUBLE; + rno = XMM0 + nsse++; + } else { + t = LONG; + rno = argregsi[ngpr++]; + } + r = block(REG, NIL, NIL, t, 0, MKAP(t)); + regno(r) = rno; + ecomp(movtomem(r, -autooff, FPREG)); + + if (tsize(sp->stype, sp->sdf, sp->sap) > SZLONG) { + r = block(REG, NIL, NIL, t, 0, MKAP(t)); + regno(r) = (typ == STRCPX ? + XMM0 + nsse++ : argregsi[ngpr++]); + ecomp(movtomem(r, -autooff+SZLONG, FPREG)); + } + + sp->soffset = -autooff; + break; + + default: + cerror("bfcode: %d", typ); + } + } + + /* Check if there are varargs */ + if (cftnsp->sdf == NULL || cftnsp->sdf->dfun == NULL) + return; /* no prototype */ + al = cftnsp->sdf->dfun; + + for (; al->type != TELLIPSIS; al++) { + t = al->type; + if (t == TNULL) + return; + if (BTYPE(t) == STRTY || BTYPE(t) == UNIONTY) + al++; + for (; t > BTMASK; t = DECREF(t)) + if (ISARY(t) || ISFTN(t)) + al++; + } + + /* fix stack offset */ + SETOFF(autooff, ALMAX); + + /* Save reg arguments in the reg save area */ + p = NIL; + for (i = ngpr; i < 6; i++) { + r = block(REG, NIL, NIL, LONG, 0, MKAP(LONG)); + regno(r) = argregsi[i]; + r = movtomem(r, -RSALONGOFF(i)-autooff, FPREG); + p = (p == NIL ? r : block(COMOP, p, r, INT, 0, MKAP(INT))); + } + for (i = nsse; i < 8; i++) { + r = block(REG, NIL, NIL, DOUBLE, 0, MKAP(DOUBLE)); + regno(r) = i + XMM0; + r = movtomem(r, -RSADBLOFF(i)-autooff, FPREG); + p = (p == NIL ? r : block(COMOP, p, r, INT, 0, MKAP(INT))); + } + autooff += RSASZ; + rsaoff = autooff; + thissse = nsse; + thisgpr = ngpr; + thisrsp = nrsp; + + ecomp(p); +} + + +/* + * by now, the automatics and register variables are allocated + */ +void +bccode() +{ + SETOFF(autooff, SZINT); +} + +/* called just before final exit */ +/* flag is 1 if errors, 0 if none */ +void +ejobcode(int flag ) +{ + if (flag) + return; + +#ifdef MACHOAPI +#define PT(x) +#else +#define PT(x) printf(".type __pcc_" x ",@function\n") +#endif + + /* printout varargs routines if used */ + if (varneeds & NEED_GPNEXT) { + printf(".text\n.align 4\n"); + PT("gpnext"); + printf("__pcc_gpnext:\n"); + printf("cmpl $48,(%%rdi)\njae 1f\n"); + printf("movl (%%rdi),%%eax\naddq 16(%%rdi),%%rax\n"); + printf("movq (%%rax),%%rax\naddl $8,(%%rdi)\nret\n"); + printf("1:movq 8(%%rdi),%%rax\nmovq (%%rax),%%rax\n"); + printf("addq $8,8(%%rdi)\nret\n"); + } + if (varneeds & NEED_FPNEXT) { + printf(".text\n.align 4\n"); + PT("fpnext"); + printf("__pcc_fpnext:\n"); + printf("cmpl $176,4(%%rdi)\njae 1f\n"); + printf("movl 4(%%rdi),%%eax\naddq 16(%%rdi),%%rax\n"); + printf("movsd (%%rax),%%xmm0\naddl $16,4(%%rdi)\nret\n"); + printf("1:movq 8(%%rdi),%%rax\nmovsd (%%rax),%%xmm0\n"); + printf("addq $8,8(%%rdi)\nret\n"); + } + if (varneeds & NEED_1REGREF) { + printf(".text\n.align 4\n"); + PT("1regref"); + printf("__pcc_1regref:\n"); + printf("cmpl $48,(%%rdi)\njae 1f\n"); + printf("movl (%%rdi),%%eax\naddq 16(%%rdi),%%rax\n"); + printf("addl $8,(%%rdi)\nret\n"); + printf("1:movq 8(%%rdi),%%rax\n"); + printf("addq $8,8(%%rdi)\nret\n"); + } + if (varneeds & NEED_2REGREF) { + printf(".text\n.align 4\n"); + PT("2regref"); + printf("__pcc_2regref:\n"); + printf("cmpl $40,(%%rdi)\njae 1f\n"); + printf("movl (%%rdi),%%eax\naddq 16(%%rdi),%%rax\n"); + printf("addl $16,(%%rdi)\nret\n"); + printf("1:movq 8(%%rdi),%%rax\n"); + printf("addq $16,8(%%rdi)\nret\n"); + } + if (varneeds & NEED_MEMREF) { + printf(".text\n.align 4\n"); + PT("memref"); + printf("__pcc_memref:\n"); + printf("movq 8(%%rdi),%%rax\n"); + printf("addq %%rsi,8(%%rdi)\nret\n"); + } + + +#define _MKSTR(x) #x +#define MKSTR(x) _MKSTR(x) +#define OS MKSTR(TARGOS) +#ifdef MACHOABI + printf("\t.ident \"PCC: %s (%s)\"\n", PACKAGE_STRING, OS); +#else + printf("\t.ident \"PCC: %s (%s)\"\n\t.end\n", PACKAGE_STRING, OS); +#endif +} + +/* + * Varargs stuff: + * The ABI says that va_list should be declared as this typedef. + * We handcraft it here and then just reference it. + * + * typedef struct { + * unsigned int gp_offset; + * unsigned int fp_offset; + * void *overflow_arg_area; + * void *reg_save_area; + * } __builtin_va_list[1]; + * + * There are a number of asm routines printed out if varargs are used: + * long __pcc_gpnext(va) - get a gpreg value + * long __pcc_fpnext(va) - get a fpreg value + * void *__pcc_1regref(va) - get reference to a onereg struct + * void *__pcc_2regref(va) - get reference to a tworeg struct + * void *__pcc_memref(va,sz) - get reference to a large struct + */ + +static char *gp_offset, *fp_offset, *overflow_arg_area, *reg_save_area; +static char *gpnext, *fpnext, *_1regref, *_2regref, *memref; + +void +bjobcode() +{ + struct symtab *sp; + struct rstack *rp; + NODE *p, *q; + char *c; + + gp_offset = addname("gp_offset"); + fp_offset = addname("fp_offset"); + overflow_arg_area = addname("overflow_arg_area"); + reg_save_area = addname("reg_save_area"); + + rp = bstruct(NULL, STNAME, NULL); + p = block(NAME, NIL, NIL, UNSIGNED, 0, MKAP(UNSIGNED)); + soumemb(p, gp_offset, 0); + soumemb(p, fp_offset, 0); + p->n_type = VOID+PTR; + p->n_ap = MKAP(VOID); + soumemb(p, overflow_arg_area, 0); + soumemb(p, reg_save_area, 0); + nfree(p); + q = dclstruct(rp); + c = addname("__builtin_va_list"); + p = block(LB, bdty(NAME, c), bcon(1), INT, 0, MKAP(INT)); + p = tymerge(q, p); + p->n_sp = lookup(c, 0); + defid(p, TYPEDEF); + nfree(q); + nfree(p); + + /* for the static varargs functions */ +#define MKN(vn, rn, tp) \ + { vn = addname(rn); sp = lookup(vn, SNORMAL); \ + sp->sclass = USTATIC; sp->stype = tp; } + + MKN(gpnext, "__pcc_gpnext", FTN|LONG); + MKN(fpnext, "__pcc_fpnext", FTN|DOUBLE); + MKN(_1regref, "__pcc_1regref", FTN|VOID|(PTR<n_left; + r = buildtree(ASSIGN, structref(ccopy(p), STREF, reg_save_area), + mkstkref(-rsaoff, VOID)); + r = buildtree(COMOP, r, + buildtree(ASSIGN, structref(ccopy(p), STREF, overflow_arg_area), + mkstkref(thisrsp, VOID))); + r = buildtree(COMOP, r, + buildtree(ASSIGN, structref(ccopy(p), STREF, gp_offset), + bcon(thisgpr*(SZLONG/SZCHAR)))); + r = buildtree(COMOP, r, + buildtree(ASSIGN, structref(ccopy(p), STREF, fp_offset), + bcon(thissse*(SZDOUBLE*2/SZCHAR)+48))); + + tfree(f); + tfree(a); + return r; +} + +NODE * +amd64_builtin_va_arg(NODE *f, NODE *a, TWORD t) +{ + NODE *ap, *r, *dp; + + ap = a->n_left; + dp = a->n_right; + if (dp->n_type <= ULONGLONG || ISPTR(dp->n_type) || + dp->n_type == FLOAT || dp->n_type == DOUBLE) { + /* type might be in general register */ + if (dp->n_type == FLOAT || dp->n_type == DOUBLE) { + f->n_sp = lookup(fpnext, SNORMAL); + varneeds |= NEED_FPNEXT; + } else { + f->n_sp = lookup(gpnext, SNORMAL); + varneeds |= NEED_GPNEXT; + } + f->n_type = f->n_sp->stype = INCREF(dp->n_type) + (FTN-PTR); + f->n_ap = dp->n_ap; + f->n_df = /* dp->n_df */ NULL; + f = clocal(f); + r = buildtree(CALL, f, ccopy(ap)); + } else if (ISSOU(dp->n_type) || dp->n_type == LDOUBLE) { + /* put a reference directly to the stack */ + int sz = tsize(dp->n_type, dp->n_df, dp->n_ap); + int al = talign(dp->n_type, dp->n_ap); + if (al < ALLONG) + al = ALLONG; + if (sz <= SZLONG*2 && al == ALLONG) { + if (sz <= SZLONG) { + f->n_sp = lookup(_1regref, SNORMAL); + varneeds |= NEED_1REGREF; + } else { + f->n_sp = lookup(_2regref, SNORMAL); + varneeds |= NEED_2REGREF; + } + f->n_type = f->n_sp->stype; + f = clocal(f); + r = buildtree(CALL, f, ccopy(ap)); + r = ccast(r, INCREF(dp->n_type), 0, dp->n_df, dp->n_ap); + r = buildtree(UMUL, r, NIL); + } else { + f->n_sp = lookup(memref, SNORMAL); + varneeds |= NEED_MEMREF; + f->n_type = f->n_sp->stype; + f = clocal(f); + SETOFF(sz, al); + r = buildtree(CALL, f, + buildtree(CM, ccopy(ap), bcon(sz/SZCHAR))); + r = ccast(r, INCREF(dp->n_type), 0, dp->n_df, dp->n_ap); + r = buildtree(UMUL, r, NIL); + } + } else { + uerror("amd64_builtin_va_arg not supported type"); + goto bad; + } + tfree(a); + return r; +bad: + uerror("bad argument to __builtin_va_arg"); + return bcon(0); +} + +NODE * +amd64_builtin_va_end(NODE *f, NODE *a, TWORD t) +{ + tfree(f); + tfree(a); + return bcon(0); /* nothing */ +} + +NODE * +amd64_builtin_va_copy(NODE *f, NODE *a, TWORD t) +{ + tfree(f); + f = buildtree(ASSIGN, buildtree(UMUL, a->n_left, NIL), + buildtree(UMUL, a->n_right, NIL)); + nfree(a); + return f; +} + +static NODE * +movtoreg(NODE *p, int rno) +{ + NODE *r; + + r = block(REG, NIL, NIL, p->n_type, p->n_df, p->n_ap); + regno(r) = rno; + return clocal(buildtree(ASSIGN, r, p)); +} + +static NODE * +movtomem(NODE *p, int off, int reg) +{ + struct symtab s; + NODE *r, *l; + + s.stype = p->n_type; + s.squal = 0; + s.sdf = p->n_df; + s.sap = p->n_ap; + s.soffset = off; + s.sclass = AUTO; + + l = block(REG, NIL, NIL, PTR+STRTY, 0, 0); + l->n_lval = 0; + regno(l) = reg; + + r = block(NAME, NIL, NIL, p->n_type, p->n_df, p->n_ap); + r->n_sp = &s; + r = stref(block(STREF, l, r, 0, 0, 0)); + + return clocal(buildtree(ASSIGN, r, p)); +} + + +/* + * AMD64 parameter classification. + */ +static int +argtyp(TWORD t, union dimfun *df, struct attr *ap) +{ + int cl = 0; + + if (t <= ULONG || ISPTR(t) || t == BOOL) { + cl = ngpr < 6 ? INTEGER : INTMEM; + } else if (t == FLOAT || t == DOUBLE || t == FIMAG || t == IMAG) { + cl = nsse < 8 ? SSE : SSEMEM; + } else if (t == LDOUBLE || t == LIMAG) { + cl = X87; /* XXX */ + } else if (t == STRTY || t == UNIONTY) { + int sz = tsize(t, df, ap); + + if (sz <= 2*SZLONG && attr_find(ap, ATTR_COMPLEX) != NULL) { + cl = nsse < 7 ? STRCPX : STRMEM; + } else if (sz > 2*SZLONG || ((sz+SZLONG)/SZLONG)+ngpr > 6 || + attr_find(ap, GCC_ATYP_PACKED) != NULL) + cl = STRMEM; + else + cl = STRREG; + } else + cerror("FIXME: classify"); + return cl; +} + +/* + * Do the "hard work" in assigning correct destination for arguments. + * Also convert arguments < INT to inte (default argument promotions). + * XXX - should be dome elsewhere. + */ +static NODE * +argput(NODE *p) +{ + NODE *q; + TWORD ty; + int typ, r, ssz; + + if (p->n_op == CM) { + p->n_left = argput(p->n_left); + p->n_right = argput(p->n_right); + return p; + } + + /* first arg may be struct return pointer */ + /* XXX - check if varargs; setup al */ + switch (typ = argtyp(p->n_type, p->n_df, p->n_ap)) { + case INTEGER: + case SSE: + if (typ == SSE) + r = XMM0 + nsse++; + else + r = argregsi[ngpr++]; + if (p->n_type < INT || p->n_type == BOOL) + p = cast(p, INT, 0); + p = movtoreg(p, r); + break; + + case X87: + r = nrsp; + nrsp += SZLDOUBLE; + p = movtomem(p, r, STKREG); + break; + + case SSEMEM: + r = nrsp; + nrsp += SZDOUBLE; + p = movtomem(p, r, STKREG); + break; + + case INTMEM: + r = nrsp; + nrsp += SZLONG; + p = movtomem(p, r, STKREG); + break; + + case STRCPX: + case STRREG: /* Struct in registers */ + /* Cast to long pointer and move to the registers */ + /* XXX can overrun struct size */ + /* XXX check carefully for SSE members */ + ssz = tsize(p->n_type, p->n_df, p->n_ap); + + if (typ == STRCPX) { + ty = DOUBLE; + r = XMM0 + nsse++; + } else { + ty = LONG; + r = argregsi[ngpr++]; + } + if (ssz <= SZLONG) { + q = cast(p->n_left, INCREF(ty), 0); + nfree(p); + q = buildtree(UMUL, q, NIL); + p = movtoreg(q, r); + } else if (ssz <= SZLONG*2) { + NODE *ql, *qr; + + qr = cast(ccopy(p->n_left), INCREF(ty), 0); + qr = movtoreg(buildtree(UMUL, qr, NIL), r); + + ql = cast(p->n_left, INCREF(ty), 0); + ql = buildtree(UMUL, buildtree(PLUS, ql, bcon(1)), NIL); + r = (typ == STRCPX ? XMM0 + nsse++ : argregsi[ngpr++]); + ql = movtoreg(ql, r); + + nfree(p); + p = buildtree(CM, ql, qr); + } else + cerror("STRREG"); + break; + + case STRMEM: { + struct symtab s; + NODE *l, *t; + + q = buildtree(UMUL, p->n_left, NIL); + + s.stype = p->n_type; + s.squal = 0; + s.sdf = p->n_df; + s.sap = p->n_ap; + s.soffset = nrsp; + s.sclass = AUTO; + + nrsp += tsize(p->n_type, p->n_df, p->n_ap); + + l = block(REG, NIL, NIL, PTR+STRTY, 0, 0); + l->n_lval = 0; + regno(l) = STKREG; + + t = block(NAME, NIL, NIL, p->n_type, p->n_df, p->n_ap); + t->n_sp = &s; + t = stref(block(STREF, l, t, 0, 0, 0)); + + t = (buildtree(ASSIGN, t, q)); + nfree(p); + p = t->n_left; + nfree(t); + break; + } + + default: + cerror("argument %d", typ); + } + return p; +} + +/* + * Sort arglist so that register assignments ends up last. + */ +static int +argsort(NODE *p) +{ + NODE *q, *r; + int rv = 0; + + if (p->n_op != CM) { + if (p->n_op == ASSIGN && p->n_left->n_op == REG && + coptype(p->n_right->n_op) != LTYPE) { + q = tempnode(0, p->n_type, p->n_df, p->n_ap); + r = ccopy(q); + p->n_right = buildtree(COMOP, + buildtree(ASSIGN, q, p->n_right), r); + } + return rv; + } + if (p->n_right->n_op == CM) { + /* fixup for small structs in regs */ + q = p->n_right->n_left; + p->n_right->n_left = p->n_left; + p->n_left = p->n_right; + p->n_right = q; + } + if (p->n_right->n_op == ASSIGN && p->n_right->n_left->n_op == REG && + coptype(p->n_right->n_right->n_op) != LTYPE) { + /* move before everything to avoid reg trashing */ + q = tempnode(0, p->n_right->n_type, + p->n_right->n_df, p->n_right->n_ap); + r = ccopy(q); + p->n_right->n_right = buildtree(COMOP, + buildtree(ASSIGN, q, p->n_right->n_right), r); + } + if (p->n_right->n_op == ASSIGN && p->n_right->n_left->n_op == REG) { + if (p->n_left->n_op == CM && + p->n_left->n_right->n_op == STASG) { + q = p->n_left->n_right; + p->n_left->n_right = p->n_right; + p->n_right = q; + rv = 1; + } else if (p->n_left->n_op == STASG) { + q = p->n_left; + p->n_left = p->n_right; + p->n_right = q; + rv = 1; + } + } + return rv | argsort(p->n_left); +} + +/* + * Called with a function call with arguments as argument. + * This is done early in buildtree() and only done once. + * Returns p. + */ +NODE * +funcode(NODE *p) +{ + NODE *l, *r; + TWORD t; + + nsse = ngpr = nrsp = 0; + /* Check if hidden arg needed */ + /* If so, add it in pass2 */ + if ((l = p->n_left)->n_type == INCREF(FTN)+STRTY || + l->n_type == INCREF(FTN)+UNIONTY) { + int ssz = tsize(BTYPE(l->n_type), l->n_df, l->n_ap); + if (ssz > 2*SZLONG) + ngpr++; + } + + /* Convert just regs to assign insn's */ + p->n_right = argput(p->n_right); + + /* Must sort arglist so that STASG ends up first */ + /* This avoids registers being clobbered */ + while (argsort(p->n_right)) + ; + /* Check if there are varargs */ + if (nsse || l->n_df == NULL || l->n_df->dfun == NULL) { + ; /* Need RAX */ + } else { + union arglist *al = l->n_df->dfun; + + for (; al->type != TELLIPSIS; al++) { + if ((t = al->type) == TNULL) + return p; /* No need */ + if (BTYPE(t) == STRTY || BTYPE(t) == UNIONTY) + al++; + for (; t > BTMASK; t = DECREF(t)) + if (ISARY(t) || ISFTN(t)) + al++; + } + } + + /* Always emit number of SSE regs used */ + l = movtoreg(bcon(nsse), RAX); + if (p->n_right->n_op != CM) { + p->n_right = block(CM, l, p->n_right, INT, 0, MKAP(INT)); + } else { + for (r = p->n_right; r->n_left->n_op == CM; r = r->n_left) + ; + r->n_left = block(CM, l, r->n_left, INT, 0, MKAP(INT)); + } + return p; +} + +/* + * return the alignment of field of type t + */ +int +fldal(unsigned int t) +{ + uerror("illegal field type"); + return(ALINT); +} + +/* fix up type of field p */ +void +fldty(struct symtab *p) +{ +} + +/* + * XXX - fix genswitch. + */ +int +mygenswitch(int num, TWORD type, struct swents **p, int n) +{ + return 0; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/amd64/local.c b/compilers/pcc/pcc-1.0.0/arch/amd64/local.c new file mode 100644 index 00000000..77f8b9ad --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/amd64/local.c @@ -0,0 +1,1266 @@ +/* $Id: local.c,v 1.41.2.2 2011/03/02 17:40:07 ragge Exp $ */ +/* + * Copyright (c) 2008 Michael Shalayeff + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "pass1.h" + +/* this file contains code which is dependent on the target machine */ + +/* + * Check if a constant is too large for a type. + */ +static int +toolarge(TWORD t, CONSZ con) +{ + U_CONSZ ucon = con; + + switch (t) { + case ULONG: + case LONG: + case ULONGLONG: + case LONGLONG: + break; /* cannot be too large */ +#define SCHK(i) case i: if (con > MAX_##i || con < MIN_##i) return 1; break +#define UCHK(i) case i: if (ucon > MAX_##i) return 1; break + SCHK(INT); + SCHK(SHORT); + case BOOL: + SCHK(CHAR); + UCHK(UNSIGNED); + UCHK(USHORT); + UCHK(UCHAR); + default: + cerror("toolarge"); + } + return 0; +} + +#define IALLOC(sz) (isinlining ? permalloc(sz) : tmpalloc(sz)) + +/* + * Make a symtab entry for PIC use. + */ +static struct symtab * +picsymtab(char *p, char *s, char *s2) +{ + struct symtab *sp = IALLOC(sizeof(struct symtab)); + size_t len = strlen(p) + strlen(s) + strlen(s2) + 1; + + sp->sname = sp->soname = IALLOC(len); + strlcpy(sp->soname, p, len); + strlcat(sp->soname, s, len); + strlcat(sp->soname, s2, len); + sp->sclass = EXTERN; + sp->sflags = sp->slevel = 0; + return sp; +} + +int gotnr; /* tempnum for GOT register */ +int argstacksize; +static int ininval; + +/* + * Create a reference for an extern variable or function. + */ +static NODE * +picext(NODE *p) +{ + NODE *q; + struct symtab *sp; + char *c, *g; + + if (p->n_sp->sflags & SBEENHERE) + return p; + + c = p->n_sp->soname ? p->n_sp->soname : exname(p->n_sp->sname); +#ifdef notdef + g = ISFTN(p->n_sp->stype) ? "@PLT" : "@GOTPCREL"; +#endif + g = "@GOTPCREL"; + sp = picsymtab("", c, g); + sp->sflags = SBEENHERE; + q = block(NAME, NIL, NIL, INCREF(p->n_type), p->n_df, p->n_ap); + q->n_sp = sp; + q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap); + q->n_sp = sp; + nfree(p); + return q; +} + +#ifdef notdef +/* + * Create a reference for a static variable. + */ +static NODE * +picstatic(NODE *p) +{ + struct symtab *sp; + char *c, buf[32]; + + if (p->n_sp->slevel > 0) + snprintf(c = buf, 32, LABFMT, (int)p->n_sp->soffset); + else + c = p->n_sp->soname ? p->n_sp->soname : p->n_sp->sname; + sp = picsymtab("", c, ""); + sp->sclass = STATIC; + sp->stype = p->n_sp->stype; + p->n_sp = sp; + return p; +} +#endif + +static NODE * +cmop(NODE *l, NODE *r) +{ + return block(CM, l, r, INT, 0, MKAP(INT)); +} + +static NODE * +mkx(char *s, NODE *p) +{ + p = block(XARG, p, NIL, INT, 0, MKAP(INT)); + p->n_name = s; + return p; +} + +static char * +mk3str(char *s1, char *s2, char *s3) +{ + int len = strlen(s1) + strlen(s2) + strlen(s3) + 1; + char *sd; + + sd = inlalloc(len); + strlcpy(sd, s1, len); + strlcat(sd, s2, len); + strlcat(sd, s3, len); + return sd; +} + +/* + * Create a reference for a TLS variable. + * This is the "General dynamic" version. + */ +static NODE * +tlspic(NODE *p) +{ + NODE *q, *r, *s; + char *s1, *s2; + + /* + * .byte 0x66 + * leaq x@TLSGD(%rip),%rdi + * .word 0x6666 + * rex64 + * call __tls_get_addr@PLT + */ + + /* Need the .byte stuff around. Why? */ + /* Use inline assembler */ + q = mkx("%rdx", bcon(0)); + q = cmop(q, mkx("%rcx", bcon(0))); + q = cmop(q, mkx("%rsi", bcon(0))); + q = cmop(q, mkx("%rdi", bcon(0))); + q = cmop(q, mkx("%r8", bcon(0))); + q = cmop(q, mkx("%r9", bcon(0))); + q = cmop(q, mkx("%r10", bcon(0))); + q = cmop(q, mkx("%r11", bcon(0))); + + s = ccopy(r = tempnode(0, INCREF(p->n_type), p->n_df, p->n_ap)); + r = mkx("=a", r); + r = block(XASM, r, q, INT, 0, MKAP(INT)); + + /* Create the magic string */ + s1 = ".byte 0x66\n\tleaq "; + s2 = "@TLSGD(%%rip),%%rdi\n" + "\t.word 0x6666\n\trex64\n\tcall __tls_get_addr@PLT"; + if (p->n_sp->soname == NULL) + p->n_sp->soname = p->n_sp->sname; + r->n_name = mk3str(s1, p->n_sp->soname, s2); + + r = block(COMOP, r, s, INCREF(p->n_type), p->n_df, p->n_ap); + r = buildtree(UMUL, r, NIL); + tfree(p); + return r; +} + +/* + * The "initial exec" tls model. + */ +static NODE * +tlsinitialexec(NODE *p) +{ + NODE *q, *r, *s; + char *s1, *s2; + + /* + * movq %fs:0,%rax + * addq x@GOTTPOFF(%rip),%rax + */ + + q = bcon(0); + q->n_type = STRTY; + + s = ccopy(r = tempnode(0, INCREF(p->n_type), p->n_df, p->n_ap)); + r = mkx("=r", r); + r = block(XASM, r, q, INT, 0, MKAP(INT)); + + s1 = "movq %%fs:0,%0\n\taddq "; + s2 = "@GOTTPOFF(%%rip),%0"; + if (p->n_sp->soname == NULL) + p->n_sp->soname = p->n_sp->sname; + r->n_name = mk3str(s1, p->n_sp->soname, s2); + + r = block(COMOP, r, s, INCREF(p->n_type), p->n_df, p->n_ap); + r = buildtree(UMUL, r, NIL); + tfree(p); + return r; +} + +static NODE * +tlsref(NODE *p) +{ + struct symtab *sp = p->n_sp; + struct attr *ga; + char *c; + + if ((ga = attr_find(sp->sap, GCC_ATYP_TLSMODEL)) != NULL) { + c = ga->sarg(0); + if (strcmp(c, "initial-exec") == 0) + return tlsinitialexec(p); + else if (strcmp(c, "global-dynamic") == 0) + ; + else + werror("unsupported tls model '%s'", c); + } + return tlspic(p); +} + +static NODE * +stkblk(TWORD t) +{ + int al, tsz, off, noff; + struct attr *bt; + NODE *p; + + bt = MKAP(BTYPE(t)); + al = talign(t, bt); + tsz = (int)tsize(t, 0, bt); + + noff = autooff + tsz; + SETOFF(noff, al); + off = -noff; + autooff = noff; + + p = block(REG, NIL, NIL, INCREF(t), 0, bt); + p->n_lval = 0; + p->n_rval = FPREG; + p = buildtree(UMUL, buildtree(PLUS, p, bcon(off/SZLDOUBLE)), NIL); + return p; +} + + +/* clocal() is called to do local transformations on + * an expression tree preparitory to its being + * written out in intermediate code. + * + * the major essential job is rewriting the + * automatic variables and arguments in terms of + * REG and OREG nodes + * conversion ops which are not necessary are also clobbered here + * in addition, any special features (such as rewriting + * exclusive or) are easily handled here as well + */ +NODE * +clocal(NODE *p) +{ + + register struct symtab *q; + register NODE *r, *l; + register int o; + register int m; + TWORD t; + +#ifdef PCC_DEBUG + if (xdebug) { + printf("clocal: %p\n", p); + fwalk(p, eprint, 0); + } +#endif + switch( o = p->n_op ){ + + case NAME: + if ((q = p->n_sp) == NULL) + return p; /* Nothing to care about */ + + switch (q->sclass) { + + case PARAM: + case AUTO: + /* fake up a structure reference */ + r = block(REG, NIL, NIL, PTR+STRTY, 0, 0); + r->n_lval = 0; + r->n_rval = FPREG; + p = stref(block(STREF, r, p, 0, 0, 0)); + break; + + case USTATIC: + if (kflag == 0) + break; + /* FALLTHROUGH */ + case STATIC: +#ifdef TLS + if (q->sflags & STLS) { + p = tlsref(p); + break; + } +#endif +#ifdef notdef + if (kflag == 0) { + if (q->slevel == 0) + break; + p->n_lval = 0; + } else if (blevel > 0) { + if (!ISFTN(q->stype)) + p = picstatic(p); + } +#endif + break; + + case REGISTER: + p->n_op = REG; + p->n_lval = 0; + p->n_rval = q->soffset; + break; + + case EXTERN: + case EXTDEF: + if (q->sflags & STLS) { + p = tlsref(p); + break; + } + if (kflag == 0) + break; + if (blevel > 0) + p = picext(p); + break; + } + break; + +#if 0 + case ADDROF: + if (kflag == 0 || blevel == 0) + break; + /* char arrays may end up here */ + l = p->n_left; + if (l->n_op != NAME || + (l->n_type != ARY+CHAR && l->n_type != ARY+WCHAR_TYPE)) + break; + l = p; + p = picstatic(p->n_left); + nfree(l); + if (p->n_op != UMUL) + cerror("ADDROF error"); + l = p; + p = p->n_left; + nfree(l); + break; +#endif + + case UCALL: + case USTCALL: + /* For now, always clear eax */ + l = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + regno(l) = RAX; + p->n_right = clocal(buildtree(ASSIGN, l, bcon(0))); + p->n_op -= (UCALL-CALL); + + /* FALLTHROUGH */ + case CALL: + case STCALL: + if (p->n_type == VOID) + break; /* nothing to do */ + /* have the call at left of a COMOP to avoid arg trashing */ + if (p->n_type == LDOUBLE) { + r = stkblk(LDOUBLE); + } else + r = tempnode(0, p->n_type, p->n_df, p->n_ap); + l = ccopy(r); + p = buildtree(COMOP, buildtree(ASSIGN, r, p), l); + break; + +#ifdef notyet + case CBRANCH: + l = p->n_left; + + /* + * Remove unnecessary conversion ops. + */ + if (clogop(l->n_op) && l->n_left->n_op == SCONV) { + if (coptype(l->n_op) != BITYPE) + break; + if (l->n_right->n_op == ICON) { + r = l->n_left->n_left; + if (r->n_type >= FLOAT && r->n_type <= LDOUBLE) + break; + if (ISPTR(r->n_type)) + break; /* no opt for pointers */ + if (toolarge(r->n_type, l->n_right->n_lval)) + break; + /* Type must be correct */ + t = r->n_type; + nfree(l->n_left); + l->n_left = r; + l->n_type = t; + l->n_right->n_type = t; + } + } + break; +#endif + + case PCONV: + /* Remove redundant PCONV's. Be careful */ + l = p->n_left; + if (l->n_op == ICON) { + goto delp; + } + if (l->n_type < LONG) { + /* float etc? */ + p->n_left = block(SCONV, l, NIL, + UNSIGNED, 0, MKAP(UNSIGNED)); + break; + } + /* if left is SCONV, cannot remove */ + if (l->n_op == SCONV) + break; + + /* avoid ADDROF TEMP */ + if (l->n_op == ADDROF && l->n_left->n_op == TEMP) + break; + + if ((l->n_op == REG || l->n_op == TEMP) && ISPTR(l->n_type)) + goto delp; +#ifdef notdef + /* if conversion to another pointer type, just remove */ + /* XXX breaks ADDROF NAME */ + if (p->n_type > BTMASK && l->n_type > BTMASK) + goto delp; +#endif + break; + + delp: l->n_type = p->n_type; + l->n_qual = p->n_qual; + l->n_df = p->n_df; + l->n_ap = p->n_ap; + nfree(p); + p = l; + break; + + case SCONV: + /* Special-case shifts */ + if (p->n_type == LONG && (l = p->n_left)->n_op == LS && + l->n_type == INT && l->n_right->n_op == ICON) { + p->n_left = l->n_left; + p = buildtree(LS, p, l->n_right); + nfree(l); + break; + } + + l = p->n_left; + + /* Float conversions may need extra casts */ + if (p->n_type == FLOAT || p->n_type == DOUBLE || + p->n_type == LDOUBLE) { + if (l->n_type < INT || l->n_type == BOOL) { + p->n_left = block(SCONV, l, NIL, + ISUNSIGNED(l->n_type) ? UNSIGNED : INT, + l->n_df, l->n_ap); + break; + } + } + + if (p->n_type == l->n_type) { + nfree(p); + return l; + } + + if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 && + btattr[p->n_type].atypsz == btattr[l->n_type].atypsz) { + if (p->n_type != FLOAT && p->n_type != DOUBLE && + l->n_type != FLOAT && l->n_type != DOUBLE && + l->n_type != LDOUBLE && p->n_type != LDOUBLE) { + if (l->n_op == NAME || l->n_op == UMUL || + l->n_op == TEMP) { + l->n_type = p->n_type; + nfree(p); + return l; + } + } + } + + if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT && + coptype(l->n_op) == BITYPE && l->n_op != COMOP && + l->n_op != QUEST) { + l->n_type = p->n_type; + nfree(p); + return l; + } + + o = l->n_op; + m = p->n_type; + + if (o == ICON) { + CONSZ val = l->n_lval; + + if (!ISPTR(m)) /* Pointers don't need to be conv'd */ + switch (m) { + case BOOL: + l->n_lval = nncon(l) ? (l->n_lval != 0) : 1; + l->n_sp = NULL; + break; + case CHAR: + l->n_lval = (char)val; + break; + case UCHAR: + l->n_lval = val & 0377; + break; + case SHORT: + l->n_lval = (short)val; + break; + case USHORT: + l->n_lval = val & 0177777; + break; + case UNSIGNED: + l->n_lval = val & 0xffffffff; + break; + case INT: + l->n_lval = (int)val; + break; + case LONG: + case LONGLONG: + l->n_lval = (long long)val; + break; + case ULONG: + case ULONGLONG: + l->n_lval = val; + break; + case VOID: + break; + case LDOUBLE: + case DOUBLE: + case FLOAT: + l->n_op = FCON; + l->n_dcon = val; + break; + default: + cerror("unknown type %d", m); + } + l->n_type = m; + l->n_ap = MKAP(m); + nfree(p); + return l; + } else if (l->n_op == FCON) { + if (p->n_type == BOOL) + l->n_lval = l->n_dcon != 0.0; + else + l->n_lval = l->n_dcon; + l->n_sp = NULL; + l->n_op = ICON; + l->n_type = m; + l->n_ap = MKAP(m); + nfree(p); + return clocal(l); + } + if (DEUNSIGN(p->n_type) == SHORT && + DEUNSIGN(l->n_type) == SHORT) { + nfree(p); + p = l; + } + if ((p->n_type == CHAR || p->n_type == UCHAR || + p->n_type == SHORT || p->n_type == USHORT) && + (l->n_type == FLOAT || l->n_type == DOUBLE || + l->n_type == LDOUBLE)) { + p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_ap); + p->n_left->n_type = INT; + return p; + } + break; + + case MOD: + case DIV: + if (o == DIV && p->n_type != CHAR && p->n_type != SHORT) + break; + if (o == MOD && p->n_type != CHAR && p->n_type != SHORT) + break; + /* make it an int division by inserting conversions */ + p->n_left = block(SCONV, p->n_left, NIL, INT, 0, MKAP(INT)); + p->n_right = block(SCONV, p->n_right, NIL, INT, 0, MKAP(INT)); + p = block(SCONV, p, NIL, p->n_type, 0, MKAP(p->n_type)); + p->n_left->n_type = INT; + break; + + case PMCONV: + case PVCONV: + r = p; + p = buildtree(o == PMCONV ? MUL : DIV, p->n_left, p->n_right); + nfree(r); + break; + + case FORCE: + /* put return value in return reg */ + p->n_op = ASSIGN; + p->n_right = p->n_left; + p->n_left = block(REG, NIL, NIL, p->n_type, 0, MKAP(INT)); + t = p->n_type; + if (ISITY(t)) + t = t - (FIMAG-FLOAT); + p->n_left->n_rval = p->n_left->n_type == BOOL ? + RETREG(CHAR) : RETREG(t); + break; + + case LS: + case RS: + /* shift count must be in a char */ + if (p->n_right->n_type == CHAR || p->n_right->n_type == UCHAR) + break; + p->n_right = block(SCONV, p->n_right, NIL, + CHAR, 0, MKAP(CHAR)); + break; + } +#ifdef PCC_DEBUG + if (xdebug) { + printf("clocal end: %p\n", p); + fwalk(p, eprint, 0); + } +#endif + return(p); +} + +void +myp2tree(NODE *p) +{ + struct symtab *sp, sps; + static int dblxor, fltxor; + + if (p->n_op == UMINUS && (p->n_type == FLOAT || p->n_type == DOUBLE)) { + /* Store xor code for sign change */ + if (dblxor == 0) { + dblxor = getlab(); + fltxor = getlab(); + sps.stype = LDOUBLE; + sps.squal = CON >> TSHIFT; + sps.sflags = sps.sclass = 0; + sps.sname = sps.soname = ""; + sps.slevel = 1; + sps.sap = MKAP(LDOUBLE); /* alignment */ + sps.soffset = dblxor; + defloc(&sps); + printf("\t.long 0,0x80000000,0,0\n"); + printf(LABFMT ":\n", fltxor); + printf("\t.long 0x80000000,0,0,0\n"); + } + p->n_label = p->n_type == FLOAT ? fltxor : dblxor; + return; + } + if (p->n_op != FCON) + return; + + /* XXX should let float constants follow */ + sp = IALLOC(sizeof(struct symtab)); + sp->sclass = STATIC; + sp->sap = MKAP(p->n_type); + sp->slevel = 1; /* fake numeric label */ + sp->soffset = getlab(); + sp->sflags = 0; + sp->stype = p->n_type; + sp->squal = (CON >> TSHIFT); + + defloc(sp); + ninval(0, tsize(sp->stype, sp->sdf, sp->sap), p); + + p->n_op = NAME; + p->n_lval = 0; + p->n_sp = sp; +} + +/* + * Convert ADDROF NAME to ICON? + */ +int +andable(NODE *p) +{ + if (ininval) + return 1; + if (p->n_sp->sclass == STATIC || p->n_sp->sclass == USTATIC) + return 0; + return 1; +} + +/* + * at the end of the arguments of a ftn, set the automatic offset + */ +void +cendarg() +{ + autooff = AUTOINIT; +} + +/* + * Return 1 if a variable of type type is OK to put in register. + */ +int +cisreg(TWORD t) +{ + if (t == LDOUBLE) + return 0; + return 1; +} + +/* + * return a node, for structure references, which is suitable for + * being added to a pointer of type t, in order to be off bits offset + * into a structure + * t, d, and s are the type, dimension offset, and sizeoffset + * For pdp10, return the type-specific index number which calculation + * is based on its size. For example, short a[3] would return 3. + * Be careful about only handling first-level pointers, the following + * indirections must be fullword. + */ +NODE * +offcon(OFFSZ off, TWORD t, union dimfun *d, struct attr *ap) +{ + register NODE *p; + + if (xdebug) + printf("offcon: OFFSZ %lld type %x dim %p siz %d\n", + off, t, d, (int)tsize(t, d, ap)); + + p = bcon(0); + p->n_lval = off/SZCHAR; /* Default */ + return(p); +} + +/* + * Allocate off bits on the stack. p is a tree that when evaluated + * is the multiply count for off, t is a storeable node where to write + * the allocated address. + */ +void +spalloc(NODE *t, NODE *p, OFFSZ off) +{ + NODE *sp; + + p = buildtree(MUL, p, bcon(off/SZCHAR)); + p = buildtree(PLUS, p, bcon(30)); + p = buildtree(AND, p, xbcon(-16, NULL, LONG)); + + /* sub the size from sp */ + sp = block(REG, NIL, NIL, p->n_type, 0, MKAP(LONG)); + sp->n_lval = 0; + sp->n_rval = STKREG; + ecomp(buildtree(MINUSEQ, sp, p)); + + /* save the address of sp */ + sp = block(REG, NIL, NIL, PTR+LONG, t->n_df, t->n_ap); + sp->n_lval = 0; + sp->n_rval = STKREG; + t->n_type = sp->n_type; + ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */ + +} + +/* + * Print out a string of characters. + * Assume that the assembler understands C-style escape + * sequences. + */ +void +instring(struct symtab *sp) +{ + char *s, *str = sp->sname; + + defloc(sp); + + /* be kind to assemblers and avoid long strings */ + printf("\t.ascii \""); + for (s = str; *s != 0; ) { + if (*s++ == '\\') { + (void)esccon(&s); + } + if (s - str > 60) { + fwrite(str, 1, s - str, stdout); + printf("\"\n\t.ascii \""); + str = s; + } + } + fwrite(str, 1, s - str, stdout); + printf("\\0\"\n"); +} + +static int inbits, inval; + +/* + * set fsz bits in sequence to zero. + */ +void +zbits(OFFSZ off, int fsz) +{ + int m; + + if (idebug) + printf("zbits off %lld, fsz %d inbits %d\n", off, fsz, inbits); + if ((m = (inbits % SZCHAR))) { + m = SZCHAR - m; + if (fsz < m) { + inbits += fsz; + return; + } else { + fsz -= m; + printf("\t.byte %d\n", inval); + inval = inbits = 0; + } + } + if (fsz >= SZCHAR) { +#ifdef MACHOABI + printf("\t.space %d\n", fsz/SZCHAR); +#else + printf("\t.zero %d\n", fsz/SZCHAR); +#endif + fsz -= (fsz/SZCHAR) * SZCHAR; + } + if (fsz) { + inval = 0; + inbits = fsz; + } +} + +/* + * Initialize a bitfield. + */ +void +infld(CONSZ off, int fsz, CONSZ val) +{ + if (idebug) + printf("infld off %lld, fsz %d, val %lld inbits %d\n", + off, fsz, val, inbits); + val &= (((((CONSZ)1 << (fsz-1))-1)<<1)|1); + while (fsz + inbits >= SZCHAR) { + inval |= (val << inbits); + printf("\t.byte %d\n", inval & 255); + fsz -= (SZCHAR - inbits); + val >>= (SZCHAR - inbits); + inval = inbits = 0; + } + if (fsz) { + inval |= (val << inbits); + inbits += fsz; + } +} + +/* + * print out a constant node, may be associated with a label. + * Do not free the node after use. + * off is bit offset from the beginning of the aggregate + * fsz is the number of bits this is referring to + */ +void +ninval(CONSZ off, int fsz, NODE *p) +{ + union { float f; double d; long double l; int i[3]; } u; + struct symtab *q; + NODE st, *op = NIL; + TWORD t; + + if (coptype(p->n_op) != LTYPE) { + ininval = 1; + op = p = optim(ccopy(p)); + ininval = 0; + } + + while (p->n_op == PCONV) + p = p->n_left; + + t = p->n_type; + + if (kflag && p->n_op == NAME && ISPTR(t) && + (ISFTN(DECREF(t)) || ISSOU(BTYPE(t)))) { + /* functions as initializers will be NAME here */ + if (op == NIL) { + st = *p; + p = &st; + } + p->n_op = ICON; + } + + if (t > BTMASK) + t = LONG; /* pointer */ + + if (p->n_op == COMOP) { + NODE *r = p->n_right; + tfree(p->n_left); + nfree(p); + p = r; + } + + if (p->n_op != ICON && p->n_op != FCON) { +fwalk(p, eprint, 0); + cerror("ninval: init node not constant"); + } + + if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != LONG) + uerror("element not constant"); + + switch (t) { + case LONG: + case ULONG: + printf("\t.quad 0x%llx", p->n_lval); + if ((q = p->n_sp) != NULL) { + if ((q->sclass == STATIC && q->slevel > 0)) { + printf("+" LABFMT, q->soffset); + } else { + char *name; + if ((name = q->soname) == NULL) + name = q->sname; + /* Never any PIC stuff in static init */ + if (strchr(name, '@')) { + name = tmpstrdup(name); + *strchr(name, '@') = 0; + } + printf("+%s", name); + } + } + printf("\n"); + break; + case INT: + case UNSIGNED: + printf("\t.long 0x%x\n", (int)p->n_lval & 0xffffffff); + break; + case SHORT: + case USHORT: + printf("\t.short 0x%x\n", (int)p->n_lval & 0xffff); + break; + case BOOL: + if (p->n_lval > 1) + p->n_lval = p->n_lval != 0; + /* FALLTHROUGH */ + case CHAR: + case UCHAR: + printf("\t.byte %d\n", (int)p->n_lval & 0xff); + break; + case LDOUBLE: + u.i[2] = 0; + u.l = (long double)p->n_dcon; +#if defined(HOST_BIG_ENDIAN) + /* XXX probably broken on most hosts */ + printf("\t.long\t0x%x,0x%x,0x%x,0\n", u.i[2], u.i[1], u.i[0]); +#else + printf("\t.long\t0x%x,0x%x,0x%x,0\n", u.i[0], u.i[1], u.i[2]); +#endif + break; + case DOUBLE: + u.d = (double)p->n_dcon; +#if defined(HOST_BIG_ENDIAN) + printf("\t.long\t0x%x,0x%x\n", u.i[1], u.i[0]); +#else + printf("\t.long\t0x%x,0x%x\n", u.i[0], u.i[1]); +#endif + break; + case FLOAT: + u.f = (float)p->n_dcon; + printf("\t.long\t0x%x\n", u.i[0]); + break; + default: + cerror("ninval"); + } + if (op) + tfree(op); +} + +/* make a name look like an external name in the local machine */ +char * +exname(char *p) +{ +#ifdef MACHOABI + +#define NCHNAM 256 + static char text[NCHNAM+1]; + int i; + + if (p == NULL) + return ""; + + text[0] = '_'; + for (i=1; *p && isflags & STLS) { + if (sp->sclass == EXTERN) + sp->sclass = EXTDEF; + tbss = 1; + for (t = sp->stype; ISARY(t); t = DECREF(t)) + ; + if (t == STRTY || t == UNIONTY) { + beginit(sp); + endinit(); + } else + simpleinit(sp, bcon(0)); + return; + } + + if ((name = sp->soname) == NULL) + name = exname(sp->sname); + off = tsize(sp->stype, sp->sdf, sp->sap); + off = (off+(SZCHAR-1))/SZCHAR; +#ifdef GCC_COMPAT + { + struct attr *ga; + if ((ga = attr_find(sp->sap, GCC_ATYP_VISIBILITY)) && + strcmp(ga->sarg(0), "default")) + printf("\t.%s %s\n", ga->sarg(0), name); + } +#endif + printf(" .%scomm ", sp->sclass == STATIC ? "l" : ""); + if (sp->slevel == 0) { + printf("%s,0%o\n", name, off); + } else + printf(LABFMT ",0%o\n", sp->soffset, off); +} + +static char * +section2string(char *name, int len) +{ + char *s; + int n; + + if (strncmp(name, "link_set", 8) == 0) { + const char *postfix = ",\"aw\",@progbits"; + n = len + strlen(postfix) + 1; + s = IALLOC(n); + strlcpy(s, name, n); + strlcat(s, postfix, n); + return s; + } + + return newstring(name, len); +} + +char *nextsect; +static int gottls; +static char *alias; +static int constructor; +static int destructor; + +/* + * Give target the opportunity of handling pragmas. + */ +int +mypragma(char *str) +{ + char *a2 = pragtok(NULL); + + if (strcmp(str, "tls") == 0 && a2 == NULL) { + gottls = 1; + return 1; + } + if (strcmp(str, "constructor") == 0 || strcmp(str, "init") == 0) { + constructor = 1; + return 1; + } + if (strcmp(str, "destructor") == 0 || strcmp(str, "fini") == 0) { + destructor = 1; + return 1; + } + if (strcmp(str, "section") == 0 && a2 != NULL) { + nextsect = section2string(a2, strlen(a2)); + return 1; + } + if (strcmp(str, "alias") == 0 && a2 != NULL) { + alias = tmpstrdup(a2); + return 1; + } + + return 0; +} + +/* + * Called when a identifier has been declared. + */ +void +fixdef(struct symtab *sp) +{ + struct attr *ga; + + /* may have sanity checks here */ + if (gottls) + sp->sflags |= STLS; + gottls = 0; + +#ifdef HAVE_WEAKREF + /* not many as'es have this directive */ + if ((ga = gcc_get_attr(sp->sap, GCC_ATYP_WEAKREF)) != NULL) { + char *wr = ga->a1.sarg; + char *sn = sp->soname ? sp->soname : sp->sname; + if (wr == NULL) { + if ((ga = gcc_get_attr(sp->sap, GCC_ATYP_ALIAS))) { + wr = ga->a1.sarg; + } + } + if (wr == NULL) + printf("\t.weak %s\n", sn); + else + printf("\t.weakref %s,%s\n", sn, wr); + } else +#endif + if ((ga = attr_find(sp->sap, GCC_ATYP_ALIAS)) != NULL) { + char *an = ga->sarg(0); + char *sn = sp->soname ? sp->soname : sp->sname; + char *v; + + v = attr_find(sp->sap, GCC_ATYP_WEAK) ? "weak" : "globl"; + printf("\t.%s %s\n", v, sn); + printf("\t.set %s,%s\n", sn, an); + } + if (alias != NULL && (sp->sclass != PARAM)) { + printf("\t.globl %s\n", exname(sp->soname)); + printf("%s = ", exname(sp->soname)); + printf("%s\n", exname(alias)); + alias = NULL; + } + if ((constructor || destructor) && (sp->sclass != PARAM)) { + NODE *p = talloc(); + + p->n_op = NAME; + p->n_sp = + (struct symtab *)(constructor ? "constructor" : "destructor"); + sp->sap = attr_add(sp->sap, gcc_attr_parse(p)); + constructor = destructor = 0; + } +} + +NODE * +i386_builtin_return_address(NODE *f, NODE *a, TWORD t) +{ + int nframes; + + if (a == NULL || a->n_op != ICON) + goto bad; + + nframes = a->n_lval; + + tfree(f); + tfree(a); + + f = block(REG, NIL, NIL, PTR+VOID, 0, MKAP(VOID)); + regno(f) = FPREG; + + while (nframes--) + f = block(UMUL, f, NIL, PTR+VOID, 0, MKAP(VOID)); + + f = block(PLUS, f, bcon(4), INCREF(PTR+VOID), 0, MKAP(VOID)); + f = buildtree(UMUL, f, NIL); + + return f; +bad: + uerror("bad argument to __builtin_return_address"); + return bcon(0); +} + +NODE * +i386_builtin_frame_address(NODE *f, NODE *a, TWORD t) +{ + int nframes; + + if (a == NULL || a->n_op != ICON) + goto bad; + + nframes = a->n_lval; + + tfree(f); + tfree(a); + + f = block(REG, NIL, NIL, PTR+VOID, 0, MKAP(VOID)); + regno(f) = FPREG; + + while (nframes--) + f = block(UMUL, f, NIL, PTR+VOID, 0, MKAP(VOID)); + + return f; +bad: + uerror("bad argument to __builtin_frame_address"); + return bcon(0); +} + +void +pass1_lastchance(struct interpass *ip) +{ +} diff --git a/compilers/pcc/pcc-1.0.0/arch/amd64/local2.c b/compilers/pcc/pcc-1.0.0/arch/amd64/local2.c new file mode 100644 index 00000000..02199bda --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/amd64/local2.c @@ -0,0 +1,1185 @@ +/* $Id: local2.c,v 1.41 2011/02/18 16:52:37 ragge Exp $ */ +/* + * Copyright (c) 2008 Michael Shalayeff + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +# include "pass2.h" +# include +# include + +static int stkpos; + +void +deflab(int label) +{ + printf(LABFMT ":\n", label); +} + +static int regoff[MAXREGS]; +static TWORD ftype; +char *rbyte[], *rshort[], *rlong[]; + +/* + * Print out the prolog assembler. + * addto and regoff are already calculated. + */ +static void +prtprolog(struct interpass_prolog *ipp, int addto) +{ + int i; + + /* XXX should look if there is any need to emit this */ + printf("\tpushq %%rbp\n"); + printf("\tmovq %%rsp,%%rbp\n"); + addto = (addto+15) & ~15; /* 16-byte aligned */ + if (addto) + printf("\tsubq $%d,%%rsp\n", addto); + + /* save permanent registers */ + for (i = 0; i < MAXREGS; i++) + if (TESTBIT(ipp->ipp_regs, i)) + fprintf(stdout, "\tmovq %s,-%d(%s)\n", + rnames[i], regoff[i], rnames[FPREG]); +} + +/* + * calculate stack size and offsets + */ +static int +offcalc(struct interpass_prolog *ipp) +{ + int i, addto; + + addto = p2maxautooff; + if (addto >= AUTOINIT/SZCHAR) + addto -= AUTOINIT/SZCHAR; + for (i = 0; i < MAXREGS; i++) + if (TESTBIT(ipp->ipp_regs, i)) { + addto += SZLONG/SZCHAR; + regoff[i] = addto; + } + return addto; +} + +void +prologue(struct interpass_prolog *ipp) +{ + int addto; + + ftype = ipp->ipp_type; + +#ifdef LANG_F77 + if (ipp->ipp_vis) + printf(" .globl %s\n", ipp->ipp_name); + printf(" .align 16\n"); + printf("%s:\n", ipp->ipp_name); +#endif + /* + * We here know what register to save and how much to + * add to the stack. + */ + addto = offcalc(ipp); + prtprolog(ipp, addto); +} + +void +eoftn(struct interpass_prolog *ipp) +{ + int i; + + if (ipp->ipp_ip.ip_lbl == 0) + return; /* no code needs to be generated */ + + /* return from function code */ + for (i = 0; i < MAXREGS; i++) + if (TESTBIT(ipp->ipp_regs, i)) + fprintf(stdout, " movq -%d(%s),%s\n", + regoff[i], rnames[FPREG], rnames[i]); + + /* struct return needs special treatment */ + if (ftype == STRTY || ftype == UNIONTY) { + printf(" movl 8(%%ebp),%%eax\n"); + printf(" leave\n"); + printf(" ret $%d\n", 4); + } else { + printf(" leave\n"); + printf(" ret\n"); + } +#ifndef MACHOABI + printf("\t.size %s,.-%s\n", ipp->ipp_name, ipp->ipp_name); +#endif +} + +/* + * add/sub/... + * + * Param given: + */ +void +hopcode(int f, int o) +{ + char *str; + + switch (o) { + case PLUS: + str = "add"; + break; + case MINUS: + str = "sub"; + break; + case AND: + str = "and"; + break; + case OR: + str = "or"; + break; + case ER: + str = "xor"; + break; + default: + comperr("hopcode2: %d", o); + str = 0; /* XXX gcc */ + } + printf("%s%c", str, f); +} + +/* + * Return type size in bytes. Used by R2REGS, arg 2 to offset(). + */ +int +tlen(NODE *p) +{ + switch(p->n_type) { + case CHAR: + case UCHAR: + return(1); + + case SHORT: + case USHORT: + return(SZSHORT/SZCHAR); + + case DOUBLE: + return(SZDOUBLE/SZCHAR); + + case INT: + case UNSIGNED: + return(SZINT/SZCHAR); + + case LONG: + case ULONG: + case LONGLONG: + case ULONGLONG: + return SZLONGLONG/SZCHAR; + + default: + if (!ISPTR(p->n_type)) + comperr("tlen type %d not pointer"); + return SZPOINT(p->n_type)/SZCHAR; + } +} + +/* + * Compare two floating point numbers. + */ +static void +fcomp(NODE *p) +{ + + if (p->n_left->n_op != REG) + comperr("bad compare %p\n", p); + if ((p->n_su & DORIGHT) == 0) + expand(p, 0, " fxch\n"); + expand(p, 0, " fucomip %st(1),%st\n"); /* emit compare insn */ + expand(p, 0, " fstp %st(0)\n"); /* pop fromstack */ + zzzcode(p, 'U'); +} + +int +fldexpand(NODE *p, int cookie, char **cp) +{ + CONSZ val; + + if (p->n_op == ASSIGN) + p = p->n_left; + switch (**cp) { + case 'S': + printf("%d", UPKFSZ(p->n_rval)); + break; + case 'H': + printf("%d", UPKFOFF(p->n_rval)); + break; + case 'M': + case 'N': + val = (((((CONSZ)1 << (UPKFSZ(p->n_rval)-1))-1)<<1)|1); + val <<= UPKFOFF(p->n_rval); + if (p->n_type > UNSIGNED) + printf("0x%llx", (**cp == 'M' ? val : ~val)); + else + printf("0x%llx", (**cp == 'M' ? val : ~val)&0xffffffff); + break; + default: + comperr("fldexpand"); + } + return 1; +} + +static void +bfext(NODE *p) +{ + int ch = 0, sz = 0; + + if (ISUNSIGNED(p->n_right->n_type)) + return; + switch (p->n_right->n_type) { + case CHAR: + ch = 'b'; + sz = 8; + break; + case SHORT: + ch = 'w'; + sz = 16; + break; + case INT: + ch = 'l'; + sz = 32; + break; + case LONG: + ch = 'q'; + sz = 64; + break; + default: + comperr("bfext"); + } + + sz -= UPKFSZ(p->n_left->n_rval); + printf("\tshl%c $%d,", ch, sz); + adrput(stdout, getlr(p, 'D')); + printf("\n\tsar%c $%d,", ch, sz); + adrput(stdout, getlr(p, 'D')); + printf("\n"); +} + +static void +stasg(NODE *p) +{ + expand(p, INAREG, " leaq AL,%rdi\n"); + if (p->n_stsize >= 8) + printf("\tmovl $%d,%%ecx\n\trep movsq\n", p->n_stsize >> 3); + if (p->n_stsize & 3) + printf("\tmovsl\n"); + if (p->n_stsize & 2) + printf("\tmovsw\n"); + if (p->n_stsize & 1) + printf("\tmovsb\n"); +} + +#define E(x) expand(p, 0, x) +/* + * Generate code to convert an unsigned long to xmm float/double. + */ +static void +ultofd(NODE *p) +{ + + E(" movq AL,A1\n"); + E(" testq A1,A1\n"); + E(" js 2f\n"); + E(" cvtsi2sZfq A1,A3\n"); + E(" jmp 3f\n"); + E("2:\n"); + E(" movq A1,A2\n"); + E(" shrq A2\n"); + E(" andq $1,A1\n"); + E(" orq A1,A2\n"); + E(" cvtsi2sZfq A2,A3\n"); + E(" addsZf A3,A3\n"); + E("3:\n"); +} + +/* + * Generate code to convert an x87 long double to an unsigned long. + * This is ugly :-/ + */ +static void +ldtoul(NODE *p) +{ + int r; + + r = getlr(p, '1')->n_rval; + + E(" subq $16,%rsp\n"); + E(" movl $0x5f000000,(%rsp)\n"); /* More than long can have */ + E(" flds (%rsp)\n"); + if (p->n_left->n_op == REG) { + E(" fxch\n"); + } else + E(" fldt AL\n"); + E(" fucomi %st(1), %st\n"); + E(" jae 2f\n"); + + E(" fstp %st(1)\n"); /* Pop huge val from stack */ + E(" fnstcw (%rsp)\n"); /* store cw */ + E(" movw $0x0f3f,4(%rsp)\n");/* round towards 0 */ + E(" fldcw 4(%rsp)\n"); /* new cw */ + E(" fistpll 8(%rsp)\n"); /* save val */ + E(" fldcw (%rsp)\n"); /* fetch old cw */ + E(" movq 8(%rsp),A1\n"); + + E(" jmp 3f\n"); + + E("2:\n"); + + E(" fsubp %st, %st(1)\n"); + E(" fnstcw (%rsp)\n"); + E(" movw $0x0f3f,4(%rsp)\n"); + E(" fldcw 4(%rsp)\n"); + E(" fistpll 8(%rsp)\n"); + E(" fldcw (%rsp)\n"); + E(" movabsq $0x8000000000000000,A1\n"); + E(" xorq 8(%rsp),A1\n"); + + E("3: addq $16,%rsp\n"); +} + +/* + * Generate code to convert an SSE float/double to an unsigned long. + */ +static void +fdtoul(NODE *p) +{ + if (p->n_left->n_type == FLOAT) + E(" movabsq $0x5f000000,A1\n"); + else + E(" movabsq $0x43e0000000000000,A1\n"); + E(" movd A1,A3\n"); + E(" ucomisZg A3,AL\n"); + E(" jae 2f\n"); + E(" cvttsZg2siq AL,A1\n"); + E(" jmp 3f\n"); + E("2:\n"); + E(" subsZg A3,AL\n"); + E(" cvttsZg2siq AL,A1\n"); + E(" movabsq $0x8000000000000000,A2\n"); + E(" xorq A2,A1\n"); + E("3:\n"); +} +#undef E + +void +zzzcode(NODE *p, int c) +{ + NODE *l; + int pr, lr, s; + char **rt; + + switch (c) { + case 'A': /* swap st0 and st1 if right is evaluated second */ + if ((p->n_su & DORIGHT) == 0) { + if (logop(p->n_op)) + printf(" fxch\n"); + else + printf("r"); + } + break; + + case 'B': /* ldouble to unsigned long cast */ + ldtoul(p); + break; + + case 'b': /* float/double to unsigned long cast */ + fdtoul(p); + break; + + case 'C': /* remove from stack after subroutine call */ + pr = p->n_qual; + if (p->n_op == UCALL) + return; /* XXX remove ZC from UCALL */ + if (pr) + printf(" addq $%d, %s\n", pr, rnames[RSP]); + break; + + case 'E': /* Perform bitfield sign-extension */ + bfext(p); + break; + + case 'F': /* Structure argument */ + printf(" subq $%d,%%rsp\n", p->n_stsize); + printf(" movq %%rsp,%%rsi\n"); + stasg(p); + break; + + case 'G': /* Floating point compare */ + fcomp(p); + break; + + case 'j': /* convert unsigned long to f/d */ + ultofd(p); + break; + + case 'M': /* Output sconv move, if needed */ + l = getlr(p, 'L'); + /* XXX fixneed: regnum */ + pr = DECRA(p->n_reg, 0); + lr = DECRA(l->n_reg, 0); + if (pr == lr) + break; + printf(" movb %s,%s\n", rbyte[lr], rbyte[pr]); + l->n_rval = l->n_reg = p->n_reg; /* XXX - not pretty */ + break; + + case 'N': /* output long reg name */ + printf("%s", rlong[getlr(p, '1')->n_rval]); + break; + + case 'P': /* Put hidden argument in rdi */ + printf("\tleaq -%d(%%rbp),%%rdi\n", stkpos); + break; + + case 'Q': /* emit struct assign */ + stasg(p); + break; + + case 'R': /* print opname based on right type */ + case 'L': /* print opname based on left type */ + switch (getlr(p, c)->n_type) { + case CHAR: case UCHAR: s = 'b'; break; + case SHORT: case USHORT: s = 'w'; break; + case INT: case UNSIGNED: s = 'l'; break; + default: s = 'q'; break; + printf("%c", s); + } + break; + + case 'U': { /* output branch insn for ucomi */ + static char *fpcb[] = { "jz", "jnz", "jbe", "jc", "jnc", "ja" }; + if (p->n_op < EQ || p->n_op > GT) + comperr("bad fp branch"); + if (p->n_op == NE || p->n_op == GT || p->n_op == GE) + expand(p, 0, " jp LC\n"); + else if (p->n_op == EQ) + printf("\tjp 1f\n"); + printf(" %s ", fpcb[p->n_op - EQ]); + expand(p, 0, "LC\n"); + if (p->n_op == EQ) + printf("1:\n"); + break; + } + + case '8': /* special reg name printout (64-bit) */ + case '1': /* special reg name printout (32-bit) */ + l = getlr(p, '1'); + rt = c == '8' ? rnames : rlong; + printf("%s", rt[l->n_rval]); + break; + + case 'g': + p = p->n_left; + /* FALLTHROUGH */ + case 'f': /* float or double */ + printf("%c", p->n_type == FLOAT ? 's' : 'd'); + break; + + case 'q': /* int or long */ + printf("%c", p->n_left->n_type == LONG ? 'q' : ' '); + break; + + default: + comperr("zzzcode %c", c); + } +} + +/*ARGSUSED*/ +int +rewfld(NODE *p) +{ + return(1); +} + +int canaddr(NODE *); +int +canaddr(NODE *p) +{ + int o = p->n_op; + + if (o==NAME || o==REG || o==ICON || o==OREG || + (o==UMUL && shumul(p->n_left, SOREG))) + return(1); + return(0); +} + +/* + * Does the bitfield shape match? + */ +int +flshape(NODE *p) +{ + int o = p->n_op; + + if (o == OREG || o == REG || o == NAME) + return SRDIR; /* Direct match */ + if (o == UMUL && shumul(p->n_left, SOREG)) + return SROREG; /* Convert into oreg */ + return SRREG; /* put it into a register */ +} + +/* INTEMP shapes must not contain any temporary registers */ +/* XXX should this go away now? */ +int +shtemp(NODE *p) +{ + return 0; +#if 0 + int r; + + if (p->n_op == STARG ) + p = p->n_left; + + switch (p->n_op) { + case REG: + return (!istreg(p->n_rval)); + + case OREG: + r = p->n_rval; + if (R2TEST(r)) { + if (istreg(R2UPK1(r))) + return(0); + r = R2UPK2(r); + } + return (!istreg(r)); + + case UMUL: + p = p->n_left; + return (p->n_op != UMUL && shtemp(p)); + } + + if (optype(p->n_op) != LTYPE) + return(0); + return(1); +#endif +} + +void +adrcon(CONSZ val) +{ + printf("$" CONFMT, val); +} + +void +conput(FILE *fp, NODE *p) +{ + long val = p->n_lval; + + switch (p->n_op) { + case ICON: + if (p->n_name[0] != '\0') { + fprintf(fp, "%s", p->n_name); + if (val) + fprintf(fp, "+%ld", val); + } else + fprintf(fp, "%ld", val); + return; + + default: + comperr("illegal conput, p %p", p); + } +} + +/*ARGSUSED*/ +void +insput(NODE *p) +{ + comperr("insput"); +} + +/* + * Write out the upper address, like the upper register of a 2-register + * reference, or the next memory location. + * XXX - not needed on amd64 + */ +void +upput(NODE *p, int size) +{ + + size /= SZCHAR; + switch (p->n_op) { + case REG: + fprintf(stdout, "%%%s", &rnames[p->n_rval][3]); + break; + + case NAME: + case OREG: + p->n_lval += size; + adrput(stdout, p); + p->n_lval -= size; + break; + case ICON: + fprintf(stdout, "$" CONFMT, p->n_lval >> 32); + break; + default: + comperr("upput bad op %d size %d", p->n_op, size); + } +} + +void +adrput(FILE *io, NODE *p) +{ + int r; + char **rc; + /* output an address, with offsets, from p */ + + if (p->n_op == FLD) + p = p->n_left; + + switch (p->n_op) { + + case NAME: + if (p->n_name[0] != '\0') { + if (p->n_lval != 0) + fprintf(io, CONFMT "+", p->n_lval); + fprintf(io, "%s(%%rip)", p->n_name); + } else + fprintf(io, CONFMT, p->n_lval); + return; + + case OREG: + r = p->n_rval; + if (p->n_name[0]) + printf("%s%s", p->n_name, p->n_lval ? "+" : ""); + if (p->n_lval) + fprintf(io, "%lld", p->n_lval); + if (R2TEST(r)) { + int r1 = R2UPK1(r); + int r2 = R2UPK2(r); + int sh = R2UPK3(r); + + fprintf(io, "(%s,%s,%d)", + r1 == MAXREGS ? "" : rnames[r1], + r2 == MAXREGS ? "" : rnames[r2], sh); + } else + fprintf(io, "(%s)", rnames[p->n_rval]); + return; + case ICON: +#ifdef PCC_DEBUG + /* Sanitycheck for PIC, to catch adressable constants */ + if (kflag && p->n_name[0]) { + static int foo; + + if (foo++ == 0) { + printf("\nfailing...\n"); + fwalk(p, e2print, 0); + comperr("pass2 conput"); + } + } +#endif + /* addressable value of the constant */ + fputc('$', io); + conput(io, p); + return; + + case REG: + switch (p->n_type) { + case CHAR: + case UCHAR: + rc = rbyte; + break; + case SHORT: + case USHORT: + rc = rshort; + break; + case INT: + case UNSIGNED: + rc = rlong; + break; + default: + rc = rnames; + break; + } + fprintf(io, "%s", rc[p->n_rval]); + return; + + default: + comperr("illegal address, op %d, node %p", p->n_op, p); + return; + + } +} + +static char * +ccbranches[] = { + "je", /* jumpe */ + "jne", /* jumpn */ + "jle", /* jumple */ + "jl", /* jumpl */ + "jge", /* jumpge */ + "jg", /* jumpg */ + "jbe", /* jumple (jlequ) */ + "jb", /* jumpl (jlssu) */ + "jae", /* jumpge (jgequ) */ + "ja", /* jumpg (jgtru) */ +}; + + +/* printf conditional and unconditional branches */ +void +cbgen(int o, int lab) +{ + if (o < EQ || o > UGT) + comperr("bad conditional branch: %s", opst[o]); + printf(" %s " LABFMT "\n", ccbranches[o-EQ], lab); +} + +static void +fixcalls(NODE *p, void *arg) +{ + /* Prepare for struct return by allocating bounce space on stack */ + switch (p->n_op) { + case STCALL: + case USTCALL: + if (p->n_stsize+p2autooff > stkpos) + stkpos = p->n_stsize+p2autooff; + break; + } +} + +void +myreader(struct interpass *ipole) +{ + struct interpass *ip; + + stkpos = p2autooff; + DLIST_FOREACH(ip, ipole, qelem) { + if (ip->type != IP_NODE) + continue; + walkf(ip->ip_node, fixcalls, 0); + } + if (stkpos > p2autooff) + p2autooff = stkpos; + if (stkpos > p2maxautooff) + p2maxautooff = stkpos; + if (x2debug) + printip(ipole); +} + +/* + * Remove some PCONVs after OREGs are created. + */ +static void +pconv2(NODE *p, void *arg) +{ + NODE *q; + + if (p->n_op == PLUS) { + if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) { + if (p->n_right->n_op != ICON) + return; + if (p->n_left->n_op != PCONV) + return; + if (p->n_left->n_left->n_op != OREG) + return; + q = p->n_left->n_left; + nfree(p->n_left); + p->n_left = q; + /* + * This will be converted to another OREG later. + */ + } + } +} + +void +mycanon(NODE *p) +{ + walkf(p, pconv2, 0); +} + +void +myoptim(struct interpass *ip) +{ +} + +void +rmove(int s, int d, TWORD t) +{ + + switch (t) { + case INT: + case UNSIGNED: + printf(" movl %s,%s\n", rlong[s], rlong[d]); + break; + case CHAR: + case UCHAR: + printf(" movb %s,%s\n", rbyte[s], rbyte[d]); + break; + case SHORT: + case USHORT: + printf(" movw %s,%s\n", rshort[s], rshort[d]); + break; + case FLOAT: + printf(" movss %s,%s\n", rnames[s], rnames[d]); + break; + case DOUBLE: + printf(" movsd %s,%s\n", rnames[s], rnames[d]); + break; + case LDOUBLE: +#ifdef notdef + /* a=b()*c(); will generate this */ + /* XXX can it fail anyway? */ + comperr("bad float rmove: %d %d", s, d); +#endif + break; + default: + printf(" movq %s,%s\n", rnames[s], rnames[d]); + break; + } +} + +/* + * For class c, find worst-case displacement of the number of + * registers in the array r[] indexed by class. + */ +int +COLORMAP(int c, int *r) +{ + + switch (c) { + case CLASSA: + return r[CLASSA] < 14; + case CLASSB: + return r[CLASSB] < 16; + case CLASSC: + return r[CLASSC] < CREGCNT; + } + return 0; /* XXX gcc */ +} + +char *rnames[] = { + "%rax", "%rdx", "%rcx", "%rbx", "%rsi", "%rdi", "%rbp", "%rsp", + "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", + "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", + "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", + "%xmm15", +}; + +/* register names for shorter sizes */ +char *rbyte[] = { + "%al", "%dl", "%cl", "%bl", "%sil", "%dil", "%bpl", "%spl", + "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b", +}; +char *rshort[] = { + "%ax", "%dx", "%cx", "%bx", "%si", "%di", "%bp", "%sp", + "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w", +}; +char *rlong[] = { + "%eax", "%edx", "%ecx", "%ebx", "%esi", "%edi", "%ebp", "%esp", + "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d", +}; + + +/* + * Return a class suitable for a specific type. + */ +int +gclass(TWORD t) +{ + if (t == LDOUBLE) + return CLASSC; + if (t == FLOAT || t == DOUBLE) + return CLASSB; + return CLASSA; +} + +static int +argsiz(NODE *p) +{ + TWORD t = p->n_type; + + if (p->n_left->n_op == REG) + return 0; /* not on stack */ + if (t == LDOUBLE) + return 16; + if (p->n_op == STASG) + return p->n_stsize; + return 8; +} + +/* + * Calculate argument sizes. + */ +void +lastcall(NODE *p) +{ + NODE *op = p; + int size = 0; + + p->n_qual = 0; + if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL) + return; + for (p = p->n_right; p->n_op == CM; p = p->n_left) + size += argsiz(p->n_right); + size += argsiz(p); + size = (size+15) & ~15; + if (size) + printf(" subq $%d,%s\n", size, rnames[RSP]); + op->n_qual = size; /* XXX */ +} + +/* + * Special shapes. + */ +int +special(NODE *p, int shape) +{ + int o = p->n_op; + + switch (shape) { + case SFUNCALL: + if (o == STCALL || o == USTCALL) + return SRREG; + break; + case SPCON: + if (o != ICON || p->n_name[0] || + p->n_lval < 0 || p->n_lval > 0x7fffffff) + break; + return SRDIR; + case SMIXOR: + return tshape(p, SZERO); + case SMILWXOR: + if (o != ICON || p->n_name[0] || + p->n_lval == 0 || p->n_lval & 0xffffffff) + break; + return SRDIR; + case SMIHWXOR: + if (o != ICON || p->n_name[0] || + p->n_lval == 0 || (p->n_lval >> 32) != 0) + break; + return SRDIR; + case SCON32: + if (o != ICON || p->n_name[0]) + break; + if (p->n_lval < MIN_INT || p->n_lval > MAX_INT) + break; + return SRDIR; + default: + cerror("special: %x\n", shape); + } + return SRNOPE; +} + +/* + * Target-dependent command-line options. + */ +void +mflags(char *str) +{ +} + +/* + * Do something target-dependent for xasm arguments. + */ +int +myxasm(struct interpass *ip, NODE *p) +{ + struct interpass *ip2; + int Cmax[] = { 31, 63, 127, 0xffff, 3, 255 }; + NODE *in = 0, *ut = 0; + TWORD t; + char *w; + int reg; + int c, cw, v; + + cw = xasmcode(p->n_name); + if (cw & (XASMASG|XASMINOUT)) + ut = p->n_left; + if ((cw & XASMASG) == 0) + in = p->n_left; + + c = XASMVAL(cw); +retry: switch (c) { + case 'D': reg = RDI; break; + case 'S': reg = RSI; break; + case 'A': + case 'a': reg = RAX; break; + case 'b': reg = RBX; break; + case 'c': reg = RCX; break; + case 'd': reg = RDX; break; + + case 'x': + case 'q': + case 't': + case 'u': + p->n_name = tmpstrdup(p->n_name); + w = strchr(p->n_name, c); + *w = 'r'; /* now reg */ + return c == 'q' || c == 'x' ? 0 : 1; + + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + if (p->n_left->n_op != ICON) { + if ((c = XASMVAL1(cw))) + goto retry; + uerror("xasm arg not constant"); + } + v = p->n_left->n_lval; + if ((c == 'K' && v < -128) || + (c == 'L' && v != 0xff && v != 0xffff) || + (c != 'K' && v < 0) || + (v > Cmax[c-'I'])) + uerror("xasm val out of range"); + p->n_name = "i"; + return 1; + + default: + return 0; + } + /* If there are requested either memory or register, delete memory */ + w = p->n_name = tmpstrdup(p->n_name); + if (*w == '=') + w++; + *w++ = 'r'; + *w = 0; + + t = p->n_left->n_type; + + if (t == FLOAT || t == DOUBLE) { + p->n_label = CLASSB; + reg += 16; + } else if (t == LDOUBLE) { + p->n_label = CLASSC; + reg += 32; + } else + p->n_label = CLASSA; + + if (in && ut) + in = tcopy(in); + p->n_left = mklnode(REG, 0, reg, t); + if (ut) { + ip2 = ipnode(mkbinode(ASSIGN, ut, tcopy(p->n_left), t)); + DLIST_INSERT_AFTER(ip, ip2, qelem); + } + if (in) { + ip2 = ipnode(mkbinode(ASSIGN, tcopy(p->n_left), in, t)); + DLIST_INSERT_BEFORE(ip, ip2, qelem); + } + + return 1; +} + +void +targarg(char *w, void *arg, int n) +{ + NODE **ary = arg; + NODE *p, *q; + + if (w[1] < '0' || w[1] > (n + '0')) + uerror("bad xasm arg number %c", w[1]); + if (w[1] == (n + '0')) + p = ary[(int)w[1]-'0' - 1]; /* XXX */ + else + p = ary[(int)w[1]-'0']; + p = p->n_left; + + if (optype(p->n_op) != LTYPE) + comperr("bad xarg op %d", p->n_op); + q = tcopy(p); + if (q->n_op == REG) { + if (*w == 'k') { + q->n_type = INT; + } else if (*w != 'w') { + cerror("targarg"); /* XXX ??? */ + if (q->n_type > UCHAR) { + regno(q) = regno(q)*2+8; + if (*w == 'h') + regno(q)++; + } + q->n_type = INT; + } else + q->n_type = SHORT; + } + adrput(stdout, q); + tfree(q); +} + +/* + * target-specific conversion of numeric arguments. + */ +int +numconv(void *ip, void *p1, void *q1) +{ + NODE *p = p1, *q = q1; + int cw = xasmcode(q->n_name); + + switch (XASMVAL(cw)) { + case 'a': + case 'b': + case 'c': + case 'd': + p->n_name = tmpcalloc(2); + p->n_name[0] = XASMVAL(cw); + return 1; + default: + return 0; + } +} + +static struct { + char *name; int num; +} xcr[] = { + { "rax", RAX }, + { "rbx", RBX }, + { "rcx", RCX }, + { "rdx", RDX }, + { "rsi", RSI }, + { "rdi", RDI }, + { "st", 040 }, + { "st(0)", 040 }, + { "st(1)", 041 }, + { "st(2)", 042 }, + { "st(3)", 043 }, + { "st(4)", 044 }, + { "st(5)", 045 }, + { "st(6)", 046 }, + { "st(7)", 047 }, + { NULL, 0 }, +}; + +/* + * Check for other names of the xasm constraints registers. + */ +int xasmconstregs(char *s) +{ + int i; + + for (i = 0; xcr[i].name; i++) + if (strcmp(xcr[i].name, s) == 0) + return xcr[i].num; + return -1; +} + diff --git a/compilers/pcc/pcc-1.0.0/arch/amd64/macdefs.h b/compilers/pcc/pcc-1.0.0/arch/amd64/macdefs.h new file mode 100644 index 00000000..1c05abe2 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/amd64/macdefs.h @@ -0,0 +1,286 @@ +/* $Id: macdefs.h,v 1.17 2011/02/18 17:16:57 ragge Exp $ */ +/* + * Copyright (c) 2008 Michael Shalayeff + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Machine-dependent defines for both passes. + */ + +/* + * Convert (multi-)character constant to integer. + */ +#define makecc(val,i) lastcon = (lastcon<<8)|((val<<24)>>24); + +#define ARGINIT 128 /* # bits above fp where arguments start */ +#define AUTOINIT 0 /* # bits below fp where automatics start */ + +/* + * Storage space requirements + */ +#define SZCHAR 8 +#define SZBOOL 8 +#define SZSHORT 16 +#define SZINT 32 +#define SZLONG 64 +#define SZPOINT(t) 64 +#define SZLONGLONG 64 +#define SZFLOAT 32 +#define SZDOUBLE 64 +#define SZLDOUBLE 128 + +/* + * Alignment constraints + */ +#define ALCHAR 8 +#define ALBOOL 8 +#define ALSHORT 16 +#define ALINT 32 +#define ALLONG 64 +#define ALPOINT 64 +#define ALLONGLONG 64 +#define ALFLOAT 32 +#define ALDOUBLE 64 +#define ALLDOUBLE 128 +/* #undef ALSTRUCT amd64 struct alignment is member defined */ +#define ALSTACK 64 +#define ALMAX 128 + +/* + * Min/max values. + */ +#define MIN_CHAR -128 +#define MAX_CHAR 127 +#define MAX_UCHAR 255 +#define MIN_SHORT -32768 +#define MAX_SHORT 32767 +#define MAX_USHORT 65535 +#define MIN_INT (-0x7fffffff-1) +#define MAX_INT 0x7fffffff +#define MAX_UNSIGNED 0xffffffffU +#define MIN_LONG 0x8000000000000000L +#define MAX_LONG 0x7fffffffffffffffL +#define MAX_ULONG 0xffffffffffffffffUL +#define MIN_LONGLONG 0x8000000000000000LL +#define MAX_LONGLONG 0x7fffffffffffffffLL +#define MAX_ULONGLONG 0xffffffffffffffffULL + +/* Default char is signed */ +#undef CHAR_UNSIGNED +#define BOOL_TYPE CHAR /* what used to store _Bool */ + +/* + * Use large-enough types. + */ +typedef long long CONSZ; +typedef unsigned long long U_CONSZ; +typedef long long OFFSZ; + +#define CONFMT "%lld" /* format for printing constants */ +#define LABFMT ".L%d" /* format for printing labels */ +#define STABLBL ".LL%d" /* format for stab (debugging) labels */ +#ifdef LANG_F77 +#define BLANKCOMMON "_BLNK_" +#define MSKIREG (M(TYSHORT)|M(TYLONG)) +#define TYIREG TYLONG +#define FSZLENG FSZLONG +#define AUTOREG EBP +#define ARGREG EBP +#define ARGOFFSET 8 +#endif + +#define BACKAUTO /* stack grows negatively for automatics */ +#define BACKTEMP /* stack grows negatively for temporaries */ + +#undef FIELDOPS /* no bit-field instructions */ +#define RTOLBYTES /* bytes are numbered right to left */ + +#define ENUMSIZE(high,low) INT /* enums are always stored in full int */ + +#define FINDMOPS /* i386 has instructions that modifies memory */ + +#define CC_DIV_0 /* division by zero is safe in the compiler */ + +/* Definitions mostly used in pass2 */ + +#define BYTEOFF(x) ((x)&07) +#define wdal(k) (BYTEOFF(k)==0) +#define BITOOR(x) (x) /* bit offset to oreg offset XXX die! */ + +#define STOARG(p) +#define STOFARG(p) +#define STOSTARG(p) +#define genfcall(a,b) gencall(a,b) + +/* How many integer registers are needed? (used for stack allocation) */ +#define szty(t) (t < LONG || t == FLOAT ? 1 : t == LDOUBLE ? 4 : 2) + +/* + * The amd64 architecture has a much cleaner interface to its registers + * than the x86, even though a part of the register block comes from + * the x86 architecture. Therefore currently only two non-overlapping + * register classes are used; integer and xmm registers. + * + * All registers are given a sequential number to + * identify it which must match rnames[] in local2.c. + * + * The classes used on amd64 are: + * A - integer registers + * B - xmm registers + * C - x87 registers + */ +#define RAX 000 +#define RDX 001 +#define RCX 002 +#define RBX 003 +#define RSI 004 +#define RDI 005 +#define RBP 006 +#define RSP 007 +#define R08 010 +#define R09 011 +#define R10 012 +#define R11 013 +#define R12 014 +#define R13 015 +#define R14 016 +#define R15 017 + +#define XMM0 020 +#define XMM1 021 +#define XMM2 022 +#define XMM3 023 +#define XMM4 024 +#define XMM5 025 +#define XMM6 026 +#define XMM7 027 +#define XMM8 030 +#define XMM9 031 +#define XMM10 032 +#define XMM11 033 +#define XMM12 034 +#define XMM13 035 +#define XMM14 036 +#define XMM15 037 + +#define MAXREGS 050 /* 40 registers */ + +#define RSTATUS \ + SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|PERMREG, \ + SAREG|TEMPREG, SAREG|TEMPREG, 0, 0, \ + SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \ + SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, \ + SBREG|TEMPREG, SBREG|TEMPREG, SBREG|TEMPREG, SBREG|TEMPREG, \ + SBREG|TEMPREG, SBREG|TEMPREG, SBREG|TEMPREG, SBREG|TEMPREG, \ + SBREG|TEMPREG, SBREG|TEMPREG, SBREG|TEMPREG, SBREG|TEMPREG, \ + SBREG|TEMPREG, SBREG|TEMPREG, SBREG|TEMPREG, SBREG|TEMPREG, \ + SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, + + +/* no overlapping registers at all */ +#define ROVERLAP \ + { -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 }, + + +/* Return a register class based on the type of the node */ +#define PCLASS(p) (p->n_type == FLOAT || p->n_type == DOUBLE ? SBREG : \ + p->n_type == LDOUBLE ? SCREG : SAREG) + +#define NUMCLASS 3 /* highest number of reg classes used */ + +int COLORMAP(int c, int *r); +#define GCLASS(x) (x < 16 ? CLASSA : x < 32 ? CLASSB : CLASSC) +#define DECRA(x,y) (((x) >> (y*8)) & 255) /* decode encoded regs */ +#define ENCRD(x) (x) /* Encode dest reg in n_reg */ +#define ENCRA1(x) ((x) << 8) /* A1 */ +#define ENCRA2(x) ((x) << 16) /* A2 */ +#define ENCRA(x,y) ((x) << (8+y*8)) /* encode regs in int */ + +#define RETREG(x) (x == FLOAT || x == DOUBLE ? XMM0 : \ + x == LDOUBLE ? 32 : RAX) + +/* XXX - to die */ +#define FPREG RBP /* frame pointer */ +#define STKREG RSP /* stack pointer */ + +#define SHSTR (MAXSPECIAL+1) /* short struct */ +#define SFUNCALL (MAXSPECIAL+2) /* struct assign after function call */ +#define SPCON (MAXSPECIAL+3) /* positive nonnamed constant */ + +/* + * Specials that indicate the applicability of machine idioms. + */ +#define SMIXOR (MAXSPECIAL+4) +#define SMILWXOR (MAXSPECIAL+5) +#define SMIHWXOR (MAXSPECIAL+6) +#define SCON32 (MAXSPECIAL+7) /* 32-bit constant */ + +/* + * i386-specific symbol table flags. + */ +#define SBEENHERE SLOCAL1 +#define STLS SLOCAL2 + +/* + * Extended assembler macros. + */ +int xasmconstregs(char *); +void targarg(char *w, void *arg, int n); +#define XASM_TARGARG(w, ary) \ + (w[1] == 'b' || w[1] == 'h' || w[1] == 'w' || w[1] == 'k' ? \ + w++, targarg(w, ary, n), 1 : 0) +int numconv(void *ip, void *p, void *q); +#define XASM_NUMCONV(ip, p, q) numconv(ip, p, q) +#define XASMCONSTREGS(x) xasmconstregs(x) + +/* + * builtins. + */ +#define TARGET_VALIST +#define TARGET_STDARGS +#define TARGET_BUILTINS \ + { "__builtin_stdarg_start", amd64_builtin_stdarg_start, 2 }, \ + { "__builtin_va_start", amd64_builtin_stdarg_start, 2 }, \ + { "__builtin_va_arg", amd64_builtin_va_arg, 2 }, \ + { "__builtin_va_end", amd64_builtin_va_end, 1 }, \ + { "__builtin_va_copy", amd64_builtin_va_copy, 2 }, \ + { "__builtin_frame_address", i386_builtin_frame_address, -1 }, \ + { "__builtin_return_address", i386_builtin_return_address, -1 }, + +#define NODE struct node +struct node; +NODE *amd64_builtin_stdarg_start(NODE *f, NODE *a, unsigned int); +NODE *amd64_builtin_va_arg(NODE *f, NODE *a, unsigned int); +NODE *amd64_builtin_va_end(NODE *f, NODE *a, unsigned int); +NODE *amd64_builtin_va_copy(NODE *f, NODE *a, unsigned int); +NODE *i386_builtin_frame_address(NODE *f, NODE *a, unsigned int); +NODE *i386_builtin_return_address(NODE *f, NODE *a, unsigned int); +#undef NODE diff --git a/compilers/pcc/pcc-1.0.0/arch/amd64/order.c b/compilers/pcc/pcc-1.0.0/arch/amd64/order.c new file mode 100644 index 00000000..f52fc8d5 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/amd64/order.c @@ -0,0 +1,358 @@ +/* $Id: order.c,v 1.14 2011/02/18 17:08:31 ragge Exp $ */ +/* + * Copyright (c) 2008 Michael Shalayeff + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass2.h" + +#include + +int canaddr(NODE *); + +/* is it legal to make an OREG or NAME entry which has an + * offset of off, (from a register of r), if the + * resulting thing had type t */ +int +notoff(TWORD t, int r, CONSZ off, char *cp) +{ + return(0); /* YES */ +} + +/* + * Check if LS and try to make it indexable. + * Ignore SCONV to long. + * Return 0 if failed. + */ +static int +findls(NODE *p, int check) +{ + CONSZ c; + + if (p->n_op == SCONV && p->n_type == LONG && p->n_left->n_type == INT) + p = p->n_left; /* Ignore pointless SCONVs here */ + if (p->n_op != LS || p->n_right->n_op != ICON) + return 0; + if ((c = p->n_right->n_lval) != 1 && c != 2 && c != 3) + return 0; + if (check == 1 && p->n_left->n_op != REG) + return 0; + if (!isreg(p->n_left)) + (void)geninsn(p->n_left, INAREG); + return 1; +} + +/* + * Turn a UMUL-referenced node into OREG. + * Be careful about register classes, this is a place where classes change. + * + * AMD64 (and i386) have a quite powerful addressing scheme: + * : 4(%rax) 4 + %rax + * : 4(%rbx,%rax,8) 4 + %rbx + %rax * 8 + * : 4(,%rax) 4 + %rax * 8 + * The 8 above can be 1,2,4 or 8. + */ +void +offstar(NODE *p, int shape) +{ + NODE *l; + + if (x2debug) { + printf("offstar(%p)\n", p); + fwalk(p, e2print, 0); + } + + if (isreg(p)) + return; /* Matched (%rax) */ + + if (findls(p, 0)) + return; /* Matched (,%rax,8) */ + + if ((p->n_op == PLUS || p->n_op == MINUS) && p->n_left->n_op == ICON) { + l = p->n_right; + if (isreg(l)) + return; /* Matched 4(%rax) */ + if (findls(l, 0)) + return; /* Matched 4(,%rax,8) */ + if (l->n_op == PLUS && isreg(l->n_right)) { + if (findls(l->n_left, 0)) + return; /* Matched 4(%rbx,%rax,8) */ + (void)geninsn(l->n_left, INAREG); + return; /* Generate 4(%rbx,%rax) */ + } + (void)geninsn(l, INAREG); + return; /* Generate 4(%rbx) */ + } + + if (p->n_op == PLUS) { + if (!isreg(p->n_left)) /* ensure right is REG */ + (void)geninsn(p->n_left, INAREG); + if (isreg(p->n_right)) + return; /* Matched (%rax,%rbx) */ + if (findls(p->n_right, 0)) + return; /* Matched (%rax,%rbx,4) */ + (void)geninsn(p->n_right, INAREG); + return; /* Generate (%rbx,%rax) */ + } + + (void)geninsn(p, INAREG); +} + +/* + * Do the actual conversion of offstar-found OREGs into real OREGs. + * For simple OREGs conversion should already be done. + */ +void +myormake(NODE *q) +{ + static int shtbl[] = { 1,2,4,8 }; + NODE *p, *r; + CONSZ c = 0; + int r1, r2, sh; + int mkconv = 0; + char *n = ""; + +#define risreg(p) (p->n_op == REG) + if (x2debug) { + printf("myormake(%p)\n", q); + fwalk(q, e2print, 0); + } + r1 = r2 = MAXREGS; + sh = 1; + + r = p = q->n_left; + + if ((p->n_op == PLUS || p->n_op == MINUS) && p->n_left->n_op == ICON) { + c = p->n_left->n_lval; + n = p->n_left->n_name; + p = p->n_right; + } + + if (p->n_op == PLUS && risreg(p->n_left)) { + r1 = regno(p->n_left); + p = p->n_right; + } + + if (findls(p, 1)) { + if (p->n_op == SCONV) + p = p->n_left; + sh = shtbl[(int)p->n_right->n_lval]; + r2 = regno(p->n_left); + mkconv = 1; + } else if (risreg(p)) { + r2 = regno(p); + mkconv = 1; + } //else + // comperr("bad myormake tree"); + + if (mkconv == 0) + return; + + q->n_op = OREG; + q->n_lval = c; + q->n_rval = R2PACK(r1, r2, sh); + q->n_name = n; + tfree(r); + if (x2debug) { + printf("myormake converted %p\n", q); + fwalk(q, e2print, 0); + } +} + +/* + * Shape matches for UMUL. Cooperates with offstar(). + */ +int +shumul(NODE *p, int shape) +{ + + if (x2debug) + printf("shumul(%p)\n", p); + + /* Turns currently anything into OREG on x86 */ + if (shape & SOREG) + return SROREG; + return SRNOPE; +} + +/* + * Rewrite operations on binary operators (like +, -, etc...). + * Called as a result of table lookup. + */ +int +setbin(NODE *p) +{ + + if (x2debug) + printf("setbin(%p)\n", p); + return 0; + +} + +/* setup for assignment operator */ +int +setasg(NODE *p, int cookie) +{ + if (x2debug) + printf("setasg(%p)\n", p); + return(0); +} + +/* setup for unary operator */ +int +setuni(NODE *p, int cookie) +{ + return 0; +} + +/* + * Special handling of some instruction register allocation. + */ +struct rspecial * +nspecial(struct optab *q) +{ + switch (q->op) { + case SCONV: + if ((q->ltype & TINT) && + q->rtype == (TLONGLONG|TULONGLONG|TLONG|TULONG)) { + static struct rspecial s[] = { + { NLEFT, RAX }, { NRES, RAX }, { 0 } }; + return s; + } + break; + + case DIV: + { + static struct rspecial s[] = { + { NEVER, RAX }, { NEVER, RDX }, + { NLEFT, RAX }, { NRES, RAX }, + { NORIGHT, RDX }, { NORIGHT, RAX }, { 0 } }; + return s; + } + break; + + case MOD: + if (q->ltype & TUCHAR) { + static struct rspecial s[] = { + { NEVER, RAX }, + { NLEFT, RAX }, { NRES, RAX }, + { NORIGHT, RAX }, { 0 } }; + return s; + } else { + static struct rspecial s[] = { + { NEVER, RAX }, { NEVER, RDX }, + { NLEFT, RAX }, { NRES, RDX }, + { NORIGHT, RDX }, { NORIGHT, RAX }, { 0 } }; + return s; + } + break; + + case STARG: + { + static struct rspecial s[] = { + { NEVER, RDI }, + { NLEFT, RSI }, + { NEVER, RCX }, { 0 } }; + return s; + } + + case STASG: + { + static struct rspecial s[] = { + { NEVER, RDI }, + { NRIGHT, RSI }, { NOLEFT, RSI }, + { NOLEFT, RCX }, { NORIGHT, RCX }, + { NEVER, RCX }, { 0 } }; + return s; + } + + case MUL: + if (q->lshape == SAREG) { + static struct rspecial s[] = { + { NEVER, RAX }, + { NLEFT, RAX }, { NRES, RAX }, { 0 } }; + return s; + } + break; + + case LS: + case RS: + { + static struct rspecial s[] = { + { NRIGHT, RCX }, { NOLEFT, RCX }, { 0 } }; + return s; + } + break; + + default: + break; + } + comperr("nspecial entry %d", q - table); + return 0; /* XXX gcc */ +} + +/* + * Set evaluation order of a binary node if it differs from default. + */ +int +setorder(NODE *p) +{ + return 0; /* nothing differs on x86 */ +} + +/* + * set registers in calling conventions live. + */ +int * +livecall(NODE *p) +{ + static int r[NTEMPREG+1]; + NODE *q; + int cr = 0; + + if (optype(p->n_op) != BITYPE) + return r[0] = -1, r; + + for (q = p->n_right; q->n_op == CM; q = q->n_left) { + if (q->n_right->n_op == ASSIGN && + q->n_right->n_left->n_op == REG) + r[cr++] = regno(q->n_right->n_left); + } + if (q->n_op == ASSIGN && q->n_left->n_op == REG) + r[cr++] = regno(q->n_left); + r[cr++] = -1; + return r; +} + +/* + * Signal whether the instruction is acceptable for this target. + */ +int +acceptable(struct optab *op) +{ + return 1; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/amd64/table.c b/compilers/pcc/pcc-1.0.0/arch/amd64/table.c new file mode 100644 index 00000000..757b602c --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/amd64/table.c @@ -0,0 +1,1594 @@ +/* $Id: table.c,v 1.45 2011/02/18 17:08:31 ragge Exp $ */ +/* + * Copyright (c) 2008 Michael Shalayeff + * Copyright (c) 2008 Anders Magnusson (ragge@ludd.ltu.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass2.h" + +#define TLL TLONG|TULONG +# define ANYSIGNED TINT|TSHORT|TCHAR +# define ANYUSIGNED TUNSIGNED|TUSHORT|TUCHAR +# define ANYFIXED ANYSIGNED|ANYUSIGNED +# define TUWORD TUNSIGNED +# define TSWORD TINT +# define TWORD TUWORD|TSWORD +#define TANYINT TLL|ANYFIXED +#define SHINT SAREG /* Any integer */ +#define ININT INAREG +#define SHFL SCREG /* shape for long double */ +#define INFL INCREG /* shape for long double */ + +struct optab table[] = { +/* First entry must be an empty entry */ +{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", }, + +/* PCONVs are usually not necessary */ +{ PCONV, INAREG, + SAREG, TLL|TPOINT, + SAREG, TLL|TPOINT, + 0, RLEFT, + "", }, + +{ PCONV, INAREG, + SAREG|SOREG|SNAME, TUWORD, + SAREG, TPOINT, + NASL|NAREG, RESC1, + " movl AL,Z1\n", },/* amd64 zero-extends 32-bit movl */ + + +/* + * On amd64 casts from larger to smaller integer type in register do nothing. + */ +/* 64-bit to smaller */ +{ SCONV, INAREG, + SAREG, TLL|TPOINT, + SAREG, TANYINT, + 0, RLEFT, + "", }, + +/* 32-bit to smaller */ +{ SCONV, INAREG, + SAREG, TWORD, + SAREG, ANYFIXED, + 0, RLEFT, + "", }, + +/* 16-bit to smaller */ +{ SCONV, INAREG, + SAREG, TSHORT|TUSHORT, + SAREG, TUSHORT|TUCHAR|TSHORT|TCHAR, + 0, RLEFT, + "", }, + +/* 8-bit to 8-bit */ +{ SCONV, INAREG, + SAREG, TCHAR|TUCHAR, + SAREG, TUCHAR|TCHAR, + 0, RLEFT, + "", }, + +/* + * Casts from memory to same or smaller register is equally simple. + */ +/* 64-bit to smaller */ +{ SCONV, INAREG, + SNAME|SOREG, TLL|TPOINT, + SAREG, TANYINT, + NAREG, RESC1, + " movZR AL,A1\n", }, + +/* 32-bit to smaller */ +{ SCONV, INAREG, + SNAME|SOREG, TWORD, + SAREG, ANYFIXED, + NAREG, RESC1, + " movZR AL,A1\n", }, + +/* 16-bit to smaller */ +{ SCONV, INAREG, + SNAME|SOREG, TSHORT|TUSHORT, + SAREG, TUSHORT|TUCHAR|TSHORT|TCHAR, + NAREG, RESC1, + " movZR AL,A1\n", }, + +/* 8-bit to 8-bit */ +{ SCONV, INAREG, + SNAME|SOREG, TCHAR|TUCHAR, + SAREG, TUCHAR|TCHAR, + NAREG, RESC1, + " movZR AL,A1\n", }, + + +/* char to something */ + +/* convert char to (unsigned) short. */ +{ SCONV, ININT, + SAREG|SOREG|SNAME, TCHAR, + SAREG, TSHORT|TUSHORT, + NASL|NAREG, RESC1, + " movsbw AL,A1\n", }, + +/* convert unsigned char to (u)short. */ +{ SCONV, ININT, + SAREG|SOREG|SNAME, TUCHAR, + SAREG, TSHORT|TUSHORT, + NASL|NAREG, RESC1, + " movzbw AL,A1\n", }, + +/* convert signed char to int (or pointer). */ +{ SCONV, ININT, + SAREG|SOREG|SNAME, TCHAR, + SAREG, TWORD|TPOINT, + NASL|NAREG, RESC1, + " movsbl AL,A1\n", }, + +/* convert unsigned char to (u)int. */ +{ SCONV, ININT, + SAREG|SOREG|SNAME, TUCHAR, + SAREG, TWORD, + NASL|NAREG, RESC1, + " movzbl AL,A1\n", }, + +/* convert char to (u)long long */ +{ SCONV, INAREG, + SAREG|SOREG|SNAME, TCHAR, + SANY, TLL, + NAREG|NASL, RESC1, + " movsbq AL,A1\n", }, + +/* convert unsigned char to (u)long long */ +{ SCONV, INAREG, + SAREG|SOREG|SNAME, TUCHAR, + SANY, TLL, + NAREG|NASL, RESC1, + " movzbq AL,A1\n", }, + +/* short to something */ + +/* convert short to (u)int. */ +{ SCONV, ININT, + SAREG|SOREG|SNAME, TSHORT, + SAREG, TWORD, + NASL|NAREG, RESC1, + " movswl AL,A1\n", }, + +/* convert unsigned short to (u)int. */ +{ SCONV, ININT, + SAREG|SOREG|SNAME, TUSHORT, + SAREG, TWORD, + NASL|NAREG, RESC1, + " movzwl AL,A1\n", }, + +/* convert short to (u)long long */ +{ SCONV, INAREG, + SAREG|SOREG|SNAME, TSHORT, + SAREG, TLL, + NAREG|NASL, RESC1, + " movswq AL,A1\n", }, + +/* convert unsigned short to (u)long long */ +{ SCONV, INAREG, + SAREG|SOREG|SNAME, TUSHORT, + SAREG, TLL, + NAREG|NASL, RESC1, + " movzwq AL,A1\n", }, + +/* int to something */ + +/* convert signed int to (u)long long */ +{ SCONV, INAREG, + SAREG, TSWORD, + SAREG, TLL, + NASL|NAREG, RESC1, + " movslq AL,A1\n", }, + +/* convert unsigned int to (u)long long */ +{ SCONV, INAREG, + SAREG|SOREG|SNAME, TUWORD, + SAREG, TLL, + NASL|NAREG, RESC1, + " movl AL,Z1\n", },/* amd64 zero-extends 32-bit movl */ + +/* + * Floating point casts. amd64 uses xmm for float/double and x87 + * for long double calculations. + * + * Types smaller than int are casted to int/(unsigned). + */ +/* no casts */ +{ SCONV, INBREG, + SBREG, TFLOAT, + SBREG, TFLOAT, + 0, RLEFT, + "", }, + +{ SCONV, INBREG, + SBREG, TDOUBLE, + SBREG, TDOUBLE, + 0, RLEFT, + "", }, + +{ SCONV, INCREG, + SCREG, TLDOUBLE, + SCREG, TLDOUBLE, + 0, RLEFT, + "", }, + + +/* convert int/long to float/double */ +{ SCONV, INBREG, + SAREG|SOREG|SNAME, TINT|TLONG, + SBREG, TFLOAT|TDOUBLE, + NBREG, RESC1, + " cvtsi2sZfZq AL,A1\n", }, + +/* convert unsigned int to float/double */ +{ SCONV, INBREG, + SAREG|SOREG|SNAME, TUNSIGNED, + SBREG, TFLOAT|TDOUBLE, + NAREG|NBREG, RESC2, + " movl AL,Z1\n cvtsi2sZfq A1,A2\n", }, + +/* convert unsigned long to float/double */ +{ SCONV, INBREG, + SAREG|SOREG|SNAME, TULONG, + SBREG, TFLOAT|TDOUBLE, + NAREG*2|NASL|NBREG, RESC3, + "Zj", }, + +/* convert float/double to (u)char/(u)short/int */ +{ SCONV, INAREG, + SBREG|SOREG|SNAME, TFLOAT|TDOUBLE, + SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|INT, + NAREG, RESC1, + " cvttsZg2si AL,A1\n", }, + +/* convert float/double to unsigned int/long */ +{ SCONV, INAREG, + SBREG|SOREG|SNAME, TFLOAT|TDOUBLE, + SAREG, TUNSIGNED|TLONG, + NAREG, RESC1, + " cvttsZg2siq AL,Z8\n", }, + +/* convert float to double */ +{ SCONV, INBREG, + SBREG|SNAME|SOREG, TFLOAT, + SBREG, TDOUBLE, + NBREG|NBSL, RESC1, + " cvtss2sd AL,A1\n", }, + +/* convert double to float */ +{ SCONV, INBREG, + SBREG|SNAME|SOREG, TDOUBLE, + SBREG, TFLOAT, + NBREG|NBSL, RESC1, + " cvtsd2ss AL,A1\n", }, + +/* x87 conversions */ +/* float -> ldouble */ +{ SCONV, INCREG, + SBREG, TFLOAT, + SCREG, TLDOUBLE, + NCREG, RESC1, + "\tsubq $4,%rsp\n\tmovss AL,(%rsp)\n" + "\tflds (%rsp)\n\taddq $4,%rsp\n", }, + +/* double -> ldouble */ +{ SCONV, INCREG, + SBREG, TDOUBLE, + SCREG, TLDOUBLE, + NCREG, RESC1, + "\tsubq $8,%rsp\n\tmovsd AL,(%rsp)\n" + "\tfldl (%rsp)\n\taddq $8,%rsp\n", }, + +/* ldouble -> double */ +{ SCONV, INBREG, + SCREG, TLDOUBLE, + SBREG, TDOUBLE, + NBREG, RESC1, + "\tsubq $8,%rsp\n\tfstpl (%rsp)\n" + "\tmovsd (%rsp),A1\n\taddq $8,%rsp\n", }, + +/* ldouble -> float */ +{ SCONV, INBREG, + SCREG, TLDOUBLE, + SBREG, TFLOAT, + NBREG, RESC1, + "\tsubq $4,%rsp\n\tfstps (%rsp)\n" + "\tmovss (%rsp),A1\n\taddq $4,%rsp\n", }, + +/* convert int (in memory) to long double */ +{ SCONV, INCREG, + SOREG|SNAME, TSWORD, + SCREG, TLDOUBLE, + NCREG, RESC1, + " fildl AL\n", }, + +/* convert unsigned int to long double */ +{ SCONV, INCREG, + SAREG, TUWORD, + SCREG, TLDOUBLE, + NAREG|NASL|NCREG, RESC2, + " subq $16,%rsp\n" + " movl AL,Z1\n" + " movq A1,(%rsp)\n" + " fildll (%rsp)\n" + " addq $16,%rsp\n", }, + +/* convert int (in register) to long double */ +{ SCONV, INCREG, + SAREG, TSWORD, + SCREG, TLDOUBLE, + NCREG, RESC1, + " subq $4,%rsp\n" + " movl AL,(%rsp)\n" + " fildl (%rsp)\n" + " addq $4,%rsp\n", }, + +/* unsigned long (in reg) to long double */ +{ SCONV, INCREG, + SAREG, TULONG, + SCREG, TLDOUBLE, + NCREG, RESC1, + " subq $16,%rsp\n" + " movq AL,(%rsp)\n" + " fildll (%rsp)\n" + " cmpq $0,AL\n" + " jns 1f\n" + " movl $1602224128,(%rsp)\n" + " fadds (%rsp)\n" + " addq $16,%rsp\n" + "1:\n", }, + +/* unsigned long (in mem) to long double */ +{ SCONV, INCREG, + SNAME|SOREG, TULONG, + SCREG, TLDOUBLE, + NCREG, RESC1, + " fildll AL\n" + " cmpq $0,AL\n" + " jns 1f\n" + " push $1602224128\n" + " fadds (%rsp)\n" + " addq $8,%rsp\n" + "1:\n", }, + +/* convert float/double to unsigned long */ +{ SCONV, INAREG, + SBREG, TFLOAT|TDOUBLE, + SAREG, TULONG, + (NAREG*2)|NBREG, RESC1, + "Zb\n", }, + +/* long double to unsigned long */ +{ SCONV, INAREG, + SCREG|SNAME|SOREG, TLDOUBLE, + SAREG, TULONG, + NAREG, RESC1, + "ZB", }, + +/* ldouble -> long XXX merge with int */ +{ SCONV, INAREG, + SCREG, TLDOUBLE, + SAREG, TLONG, + NAREG, RESC1, + " subq $16,%rsp\n" + " fnstcw (%rsp)\n" + " fnstcw 4(%rsp)\n" + " movb $12,1(%rsp)\n" + " fldcw (%rsp)\n" + " fistpll 8(%rsp)\n" + " movq 8(%rsp),A1\n" + " fldcw 4(%rsp)\n" + " addq $16,%rsp\n", }, + +/* ldouble -> (u)int */ +{ SCONV, INAREG, + SCREG, TLDOUBLE, + SAREG, TINT|TUNSIGNED, + NAREG, RESC1, + " subq $16,%rsp\n" + " fnstcw (%rsp)\n" + " fnstcw 4(%rsp)\n" + " movb $12,1(%rsp)\n" + " fldcw (%rsp)\n" + " fistpl 8(%rsp)\n" + " movl 8(%rsp),A1\n" + " fldcw 4(%rsp)\n" + " addq $16,%rsp\n", }, + +/* long (in mem) -> ldouble */ +{ SCONV, INCREG, + SNAME|SOREG, TLONG, + SCREG, TLDOUBLE, + NCREG, RESC1, + " fildll AL\n", }, + +/* long (in reg) -> ldouble */ +{ SCONV, INCREG, + SAREG, TLONG, + SCREG, TLDOUBLE, + NCREG, RESC1, + " subq $16,%rsp\n" + " movq AL,(%rsp)\n" + " fildll (%rsp)\n" + " addq $16,%rsp\n", }, + + + +/* slut sconv */ + +/* + * Subroutine calls. + */ + +{ CALL, FOREFF, + SCON, TANY, + SANY, TANY, + 0, 0, + " call CL\nZC", }, + +{ UCALL, FOREFF, + SCON, TANY, + SANY, TANY, + 0, 0, + " call CL\n", }, + +{ CALL, INAREG, + SCON, TANY, + SAREG, TLL|ANYFIXED|TPOINT, + NAREG|NASL, RESC1, /* should be 0 */ + " call CL\nZC", }, + +{ UCALL, INAREG, + SCON, TANY, + SAREG, TLL|ANYFIXED|TPOINT, + NAREG|NASL, RESC1, /* should be 0 */ + " call CL\n", }, + +{ CALL, INBREG, + SCON, TANY, + SBREG, TANY, + NBREG|NBSL, RESC1, /* should be 0 */ + " call CL\nZC", }, + +{ UCALL, INBREG, + SCON, TANY, + SBREG, TANY, + NBREG|NBSL, RESC1, /* should be 0 */ + " call CL\nZC", }, + +{ CALL, INCREG, + SCON, TANY, + SCREG, TANY, + NCREG|NCSL, RESC1, /* should be 0 */ + " call CL\nZC", }, + +{ UCALL, INCREG, + SCON, TANY, + SCREG, TANY, + NCREG|NCSL, RESC1, /* should be 0 */ + " call CL\nZC", }, + + +{ CALL, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, 0, + " call *AL\nZC", }, + +{ UCALL, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, 0, + " call *AL\nZC", }, + +{ CALL, INAREG, + SAREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + " call *AL\nZC", }, + +{ UCALL, INAREG, + SAREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + " call *AL\nZC", }, + +{ CALL, INBREG, + SAREG, TANY, + SANY, TANY, + NBREG|NBSL, RESC1, /* should be 0 */ + " call *AL\nZC", }, + +{ UCALL, INBREG, + SAREG, TANY, + SANY, TANY, + NBREG|NBSL, RESC1, /* should be 0 */ + " call *AL\nZC", }, + +{ CALL, INCREG, + SAREG, TANY, + SANY, TANY, + NCREG|NCSL, RESC1, /* should be 0 */ + " call *AL\nZC", }, + +{ UCALL, INCREG, + SAREG, TANY, + SANY, TANY, + NCREG|NCSL, RESC1, /* should be 0 */ + " call *AL\nZC", }, + +/* struct return */ +{ USTCALL, FOREFF, + SCON, TANY, + SANY, TANY, + NAREG|NASL, 0, + "ZP call CL\nZC", }, + +{ USTCALL, INAREG, + SCON, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + "ZP call CL\nZC", }, + +{ USTCALL, INAREG, + SNAME|SAREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + "ZP call *AL\nZC", }, + +{ STCALL, FOREFF, + SCON, TANY, + SANY, TANY, + NAREG|NASL, 0, + "ZP call CL\nZC", }, + +{ STCALL, INAREG, + SCON, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + "ZP call CL\nZC", }, + +{ STCALL, INAREG, + SNAME|SAREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + "ZP call *AL\nZC", }, + +/* + * The next rules handle all binop-style operators. + */ +/* floating point add */ +{ PLUS, INBREG, + SBREG, TFLOAT|TDOUBLE, + SBREG|SNAME|SOREG, TFLOAT|TDOUBLE, + 0, RLEFT, + " addsZf AR,AL\n", }, + +{ PLUS, INCREG|FOREFF, + SHFL, TLDOUBLE, + SHFL, TLDOUBLE, + 0, RLEFT, + " faddp\n", }, + + +{ PLUS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TLL|TPOINT, + SONE, TANY, + 0, RLEFT, + " incq AL\n", }, + +{ PLUS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TWORD, + SONE, TANY, + 0, RLEFT, + " incl AL\n", }, + +{ PLUS, INAREG, + SAREG, TLL|TPOINT, + SCON, TWORD, + NAREG|NASL, RESC1, + " leaq CR(AL),A1\n", }, + +#ifdef notdef +/* older binutils are missing leal */ +{ PLUS, INAREG, + SAREG, TWORD, + SCON, TANY, + NAREG|NASL, RESC1, + " leal CR(AL),A1\n", }, +#endif + +{ PLUS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TSHORT|TUSHORT, + SONE, TANY, + 0, RLEFT, + " incw AL\n", }, + +{ PLUS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TCHAR|TUCHAR, + SONE, TANY, + 0, RLEFT, + " incb AL\n", }, + +#ifdef notdef +/* older binutils are missing leal */ +{ PLUS, INAREG, + SAREG, TWORD, + SAREG, TWORD, + NAREG|NASL|NASR, RESC1, + " leal (AL,AR),A1\n", }, +#endif + +{ MINUS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TLL|TPOINT, + SONE, TANY, + 0, RLEFT, + " decq AL\n", }, + +{ MINUS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TWORD, + SONE, TANY, + 0, RLEFT, + " decl AL\n", }, + +{ MINUS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TSHORT|TUSHORT, + SONE, TANY, + 0, RLEFT, + " decw AL\n", }, + +{ MINUS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TCHAR|TUCHAR, + SONE, TANY, + 0, RLEFT, + " decb AL\n", }, + +/* address as register offset, negative */ +{ MINUS, INAREG, + SAREG, TLL|TPOINT, + SPCON, TANY, + NAREG|NASL, RESC1, + " leaq -CR(AL),A1\n", }, + +{ MINUS, INBREG|FOREFF, + SBREG, TDOUBLE|TFLOAT, + SBREG|SNAME|SOREG, TDOUBLE|TFLOAT, + 0, RLEFT, + " subsZf AR,AL\n", }, + +{ MINUS, INCREG|FOREFF, + SHFL, TLDOUBLE, + SHFL, TLDOUBLE, + 0, RLEFT, + " fsubZAp\n", }, + +/* Simple r/m->reg ops */ +/* m/r |= r */ +{ OPSIMP, INAREG|FOREFF|FORCC, + SAREG|SNAME|SOREG, TLL|TPOINT, + SAREG, TLL|TPOINT, + 0, RLEFT|RESCC, + " Oq AR,AL\n", }, + +/* r |= r/m */ +{ OPSIMP, INAREG|FOREFF|FORCC, + SAREG, TLL|TPOINT, + SAREG|SNAME|SOREG, TLL|TPOINT, + 0, RLEFT|RESCC, + " Oq AR,AL\n", }, + +/* m/r |= r */ +{ OPSIMP, INAREG|FOREFF|FORCC, + SAREG|SNAME|SOREG, TWORD, + SAREG, TWORD, + 0, RLEFT|RESCC, + " Ol AR,AL\n", }, + +/* r |= r/m */ +{ OPSIMP, INAREG|FOREFF|FORCC, + SAREG, TWORD, + SAREG|SNAME|SOREG, TWORD, + 0, RLEFT|RESCC, + " Ol AR,AL\n", }, + +/* m/r |= r */ +{ OPSIMP, INAREG|FOREFF|FORCC, + SHINT|SNAME|SOREG, TSHORT|TUSHORT, + SHINT, TSHORT|TUSHORT, + 0, RLEFT|RESCC, + " Ow AR,AL\n", }, + +/* r |= r/m */ +{ OPSIMP, INAREG|FOREFF|FORCC, + SHINT, TSHORT|TUSHORT, + SHINT|SNAME|SOREG, TSHORT|TUSHORT, + 0, RLEFT|RESCC, + " Ow AR,AL\n", }, + +/* m/r |= r */ +{ OPSIMP, INAREG|FOREFF|FORCC, + SAREG, TCHAR|TUCHAR, + SAREG|SNAME|SOREG, TCHAR|TUCHAR, + 0, RLEFT|RESCC, + " Ob AR,AL\n", }, + +/* r |= r/m */ +{ OPSIMP, INAREG|FOREFF|FORCC, + SAREG, TCHAR|TUCHAR, + SAREG|SNAME|SOREG, TCHAR|TUCHAR, + 0, RLEFT|RESCC, + " Ob AR,AL\n", }, + +/* m/r |= const */ +#ifdef notdef /* amd64 lacks immediate 64-bit simple ops */ +{ OPSIMP, INAREG|FOREFF|FORCC, + SAREG|SNAME|SOREG, TLL|TPOINT, + SCON, TANY, + 0, RLEFT|RESCC, + " Oq AR,AL\n", }, +#endif + +{ OPSIMP, INAREG|FOREFF|FORCC, + SAREG|SNAME|SOREG, TWORD, + SCON, TANY, + 0, RLEFT|RESCC, + " Ol AR,AL\n", }, + +{ OPSIMP, INAREG|FOREFF|FORCC, + SHINT|SNAME|SOREG, TSHORT|TUSHORT, + SCON, TANY, + 0, RLEFT|RESCC, + " Ow AR,AL\n", }, + +{ OPSIMP, INAREG|FOREFF|FORCC, + SAREG|SNAME|SOREG, TCHAR|TUCHAR, + SCON, TANY, + 0, RLEFT|RESCC, + " Ob AR,AL\n", }, + +/* + * The next rules handle all shift operators. + */ +/* r/m <<= r */ +{ LS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TLL, + SAREG, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " salq AR,AL\n", }, + +/* r/m <<= const */ +{ LS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TLL, + SCON, TANY, + 0, RLEFT, + " salq AR,AL\n", }, + +/* r/m <<= r */ +{ LS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TWORD, + SAREG, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " sall AR,AL\n", }, + +/* r/m <<= const */ +{ LS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TWORD, + SCON, TANY, + 0, RLEFT, + " sall AR,AL\n", }, + +/* r/m <<= r */ +{ LS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TSHORT|TUSHORT, + SAREG, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " shlw AR,AL\n", }, + +/* r/m <<= const */ +{ LS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TSHORT|TUSHORT, + SCON, TANY, + 0, RLEFT, + " shlw AR,AL\n", }, + +{ LS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TCHAR|TUCHAR, + SAREG, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " salb AR,AL\n", }, + +{ LS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TCHAR|TUCHAR, + SCON, TANY, + 0, RLEFT, + " salb AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TLONG|TLONGLONG, + SAREG, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " sarq AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TLONG|TLONGLONG, + SCON, TANY, + 0, RLEFT, + " sarq AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TULONG|TULONGLONG, + SAREG, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " shrq AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TULONG|TULONGLONG, + SCON, TANY, + 0, RLEFT, + " shrq AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TSWORD, + SAREG, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " sarl AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TSWORD, + SCON, TANY, + 0, RLEFT, + " sarl AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TUWORD, + SAREG, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " shrl AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TUWORD, + SCON, TANY, + 0, RLEFT, + " shrl AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TSHORT, + SAREG, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " sarw AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TSHORT, + SCON, TANY, + 0, RLEFT, + " sarw AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TUSHORT, + SAREG, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " shrw AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TUSHORT, + SCON, TANY, + 0, RLEFT, + " shrw AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TCHAR, + SAREG, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " sarb AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TCHAR, + SCON, TANY, + 0, RLEFT, + " sarb AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TUCHAR, + SAREG, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " shrb AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TUCHAR, + SCON, TANY, + 0, RLEFT, + " shrb AR,AL\n", }, + +/* + * The next rules takes care of assignments. "=". + */ +{ ASSIGN, FORCC|FOREFF|INAREG, + SAREG, TLL|TPOINT, + SMIXOR, TANY, + 0, RDEST, + " xorq AL,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TLL|TPOINT, + SCON, TANY, + 0, RDEST, + " movabs AR,AL\n", }, + +{ ASSIGN, FORCC|FOREFF|INAREG, + SAREG, TWORD, + SMIXOR, TANY, + 0, RDEST, + " xorl AL,AL\n", }, + +{ ASSIGN, FOREFF, + SAREG|SNAME|SOREG, TWORD, + SCON, TANY, + 0, 0, + " movl AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TWORD, + SCON, TANY, + 0, RDEST, + " movl AR,AL\n", }, + +{ ASSIGN, FORCC|FOREFF|INAREG, + SAREG, TSHORT|TUSHORT, + SMIXOR, TANY, + 0, RDEST, + " xorw AL,AL\n", }, + +{ ASSIGN, FOREFF, + SAREG|SNAME|SOREG, TSHORT|TUSHORT, + SCON, TANY, + 0, 0, + " movw AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TSHORT|TUSHORT, + SCON, TANY, + 0, RDEST, + " movw AR,AL\n", }, + +{ ASSIGN, FOREFF, + SAREG|SNAME|SOREG, TCHAR|TUCHAR, + SCON, TANY, + 0, 0, + " movb AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TCHAR|TUCHAR, + SCON, TANY, + 0, RDEST, + " movb AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG|SNAME|SOREG, TLL|TPOINT, + SAREG, TLL|TPOINT, + 0, RDEST, + " movq AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG|SNAME|SOREG, TWORD, + SAREG, TWORD, + 0, RDEST, + " movl AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TWORD, + SAREG|SNAME|SOREG, TWORD, + 0, RDEST, + " movl AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TPOINT, + SAREG|SNAME|SOREG, TPOINT, + 0, RDEST, + " movq AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG|SNAME|SOREG, TSHORT|TUSHORT, + SAREG, TSHORT|TUSHORT, + 0, RDEST, + " movw AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG|SNAME|SOREG, TCHAR|TUCHAR, + SAREG, TCHAR|TUCHAR|TWORD, + 0, RDEST, + " movb AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SFLD, TCHAR|TUCHAR, + SAREG|SCON, TCHAR|TUCHAR, + NAREG*2, RDEST, + " movb AR,A2\n" + " movzbl A2,ZN\n" + " andl $N,AL\n" + " sall $H,ZN\n" + " andl $M,ZN\n" + " orl ZN,AL\n" + "F movb AR,AD\n" + "FZE", }, + +{ ASSIGN, FOREFF|INAREG, + SFLD, TSHORT|TUSHORT, + SAREG|SCON, TSHORT|TUSHORT, + NAREG, RDEST, + " movw AR,A1\n" + " movzwl A1,ZN\n" + " andl $N,AL\n" + " sall $H,ZN\n" + " andl $M,ZN\n" + " orl ZN,AL\n" + "F movw AR,AD\n" + "FZE", }, + +{ ASSIGN, FOREFF|INAREG, + SFLD, TWORD, + SAREG|SNAME|SOREG|SCON, TWORD, + NAREG, RDEST, + " movl AR,A1\n" + " andl $N,AL\n" + " sall $H,A1\n" + " andl $M,A1\n" + " orl A1,AL\n" + "F movl AR,AD\n" + "FZE", }, + +{ ASSIGN, FOREFF|INAREG, + SFLD, TLL, + SAREG|SNAME|SOREG|SCON, TLL, + NAREG*2, RDEST, + " movq AR,A1\n" + " movq $N,A2\n" + " andq A2,AL\n" + " salq $H,A1\n" + " movq $M,A2\n" + " andq A2,A1\n" + " orq A1,AL\n" + "F movq AR,AD\n" + "FZE", }, + +{ ASSIGN, INBREG|FOREFF, + SBREG, TFLOAT|TDOUBLE, + SBREG|SOREG|SNAME, TFLOAT|TDOUBLE, + 0, RDEST, + " movsZf AR,AL\n", }, + +{ ASSIGN, INBREG|FOREFF, + SBREG|SOREG|SNAME, TFLOAT|TDOUBLE, + SBREG, TFLOAT|TDOUBLE, + 0, RDEST, + " movsZf AR,AL\n", }, + +/* x87 entries */ +{ ASSIGN, INDREG|FOREFF, + SHFL, TLDOUBLE, + SHFL, TLDOUBLE, + 0, RDEST, + "", }, /* This will always be in the correct register */ + +/* order of table entries is very important here! */ +{ ASSIGN, INFL, + SNAME|SOREG, TLDOUBLE, + SHFL, TLDOUBLE, + 0, RDEST, + " fstpt AL\n fldt AL\n", }, /* XXX */ + +{ ASSIGN, FOREFF, + SNAME|SOREG, TLDOUBLE, + SHFL, TLDOUBLE, + 0, 0, + " fstpt AL\n", }, + +/* end very important order */ + +{ ASSIGN, INFL|FOREFF, + SHFL, TLDOUBLE, + SHFL|SOREG|SNAME, TLDOUBLE, + 0, RDEST, + " fldt AR\n", }, + +/* end x87 */ + +/* Do not generate memcpy if return from funcall */ +#if 0 +{ STASG, INAREG|FOREFF, + SOREG|SNAME|SAREG, TPTRTO|TSTRUCT, + SFUNCALL, TPTRTO|TSTRUCT, + 0, RRIGHT, + "", }, +#endif + +{ STASG, INAREG|FOREFF, + SOREG|SNAME, TANY, + SAREG, TPTRTO|TANY, + NSPECIAL, RDEST, + "ZQ", }, + +/* + * DIV/MOD/MUL + */ +{ DIV, INAREG, + SAREG, TLONG, + SAREG|SNAME|SOREG, TLL, + NSPECIAL, RDEST, + " cqto\n idivq AR\n", }, + +{ DIV, INAREG, + SAREG, TULONG|TPOINT, + SAREG|SNAME|SOREG, TLL|TPOINT, + NSPECIAL, RDEST, + " xorq %rdx,%rdx\n divq AR\n", }, + +{ DIV, INAREG, + SAREG, TSWORD, + SAREG|SNAME|SOREG, TWORD, + NSPECIAL, RDEST, + " cltd\n idivl AR\n", }, + +{ DIV, INAREG, + SAREG, TUWORD, + SAREG|SNAME|SOREG, TWORD, + NSPECIAL, RDEST, + " xorl %edx,%edx\n divl AR\n", }, + +{ DIV, INAREG, + SAREG, TUSHORT, + SAREG|SNAME|SOREG, TUSHORT, + NSPECIAL, RDEST, + " xorl %edx,%edx\n divw AR\n", }, + +{ DIV, INAREG, + SAREG, TUCHAR, + SAREG|SNAME|SOREG, TUCHAR, + NSPECIAL, RDEST, + " xorb %ah,%ah\n divb AR\n", }, + +{ DIV, INBREG, + SBREG, TFLOAT|TDOUBLE, + SBREG|SNAME|SOREG, TFLOAT|TDOUBLE, + 0, RLEFT, + " divsZf AR,AL\n", }, + +{ DIV, INCREG, + SHFL, TLDOUBLE, + SHFL, TLDOUBLE, + 0, RLEFT, + " fdivZAp\n", }, + +{ MOD, INAREG, + SAREG, TLONG, + SAREG|SNAME|SOREG, TLONG, + NAREG|NSPECIAL, RESC1, + " cqto\n idivq AR\n", }, + +{ MOD, INAREG, + SAREG, TLL|TPOINT, + SAREG|SNAME|SOREG, TULONG|TPOINT, + NAREG|NSPECIAL, RESC1, + " xorq %rdx,%rdx\n divq AR\n", }, + +{ MOD, INAREG, + SAREG, TSWORD, + SAREG|SNAME|SOREG, TSWORD, + NAREG|NSPECIAL, RESC1, + " cltd\n idivl AR\n", }, + +{ MOD, INAREG, + SAREG, TWORD, + SAREG|SNAME|SOREG, TUWORD, + NAREG|NSPECIAL, RESC1, + " xorl %edx,%edx\n divl AR\n", }, + +{ MOD, INAREG, + SAREG, TUSHORT, + SAREG|SNAME|SOREG, TUSHORT, + NAREG|NSPECIAL, RESC1, + " xorl %edx,%edx\n divw AR\n", }, + +{ MOD, INAREG, + SAREG, TUCHAR, + SAREG|SNAME|SOREG, TUCHAR, + NAREG|NSPECIAL, RESC1, + " xorb %ah,%ah\n divb AR\n movb %ah,%al\n", }, + +{ MUL, INAREG, + SAREG, TLL|TPOINT, + SAREG|SNAME|SOREG, TLL|TPOINT, + 0, RLEFT, + " imulq AR,AL\n", }, + +{ MUL, INAREG, + SAREG, TWORD, + SAREG|SNAME|SOREG|SCON, TWORD, + 0, RLEFT, + " imull AR,AL\n", }, + +{ MUL, INAREG, + SAREG, TSHORT|TUSHORT, + SAREG|SNAME|SOREG, TSHORT|TUSHORT, + 0, RLEFT, + " imulw AR,AL\n", }, + +{ MUL, INAREG, + SAREG, TCHAR|TUCHAR, + SAREG|SNAME|SOREG, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " imulb AR\n", }, + +{ MUL, INBREG, + SBREG, TFLOAT|TDOUBLE, + SBREG|SNAME|SOREG, TFLOAT|TDOUBLE, + 0, RLEFT, + " mulsZf AR,AL\n", }, + +{ MUL, INCREG, + SHFL, TLDOUBLE, + SHFL, TLDOUBLE, + 0, RLEFT, + " fmulp\n", }, + +/* + * Indirection operators. + */ +{ UMUL, INAREG, + SANY, TANY, + SOREG, TLL|TPOINT, + NAREG, RESC1, + " movq AL,A1\n", }, + +{ UMUL, INAREG, + SANY, TWORD, + SOREG, TWORD, + NAREG|NASL, RESC1, + " movl AL,A1\n", }, + +{ UMUL, INAREG, + SANY, TANY, + SOREG, TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " movb AL,A1\n", }, + +{ UMUL, INAREG, + SANY, TANY, + SOREG, TSHORT|TUSHORT, + NAREG|NASL, RESC1, + " movw AL,A1\n", }, + +{ UMUL, INBREG, + SANY, TANY, + SOREG, TFLOAT|TDOUBLE, + NBREG|NBSL, RESC1, + " movsZf AL,A1\n", }, + +{ UMUL, INCREG, + SANY, TANY, + SOREG, TLDOUBLE, + NCREG|NCSL, RESC1, + " fldt AL\n", }, + +/* + * Logical/branching operators + */ + +/* Comparisions, take care of everything */ + +{ OPLOG, FORCC, + SAREG, TLL|TPOINT, + SAREG|SOREG|SNAME, TLL|TPOINT, + 0, RESCC, + " cmpq AR,AL\n", }, + +{ OPLOG, FORCC, + SAREG|SOREG|SNAME, TLL|TPOINT, + SAREG, TLL|TPOINT, + 0, RESCC, + " cmpq AR,AL\n", }, + +{ OPLOG, FORCC, + SAREG|SOREG|SNAME, TLL|TPOINT, + SCON32, TANY, + 0, RESCC, + " cmpq AR,AL\n", }, + +{ OPLOG, FORCC, + SAREG|SOREG|SNAME, TWORD, + SCON|SAREG, TWORD, + 0, RESCC, + " cmpl AR,AL\n", }, + +{ OPLOG, FORCC, + SCON|SAREG, TWORD, + SAREG|SOREG|SNAME, TWORD, + 0, RESCC, + " cmpl AR,AL\n", }, + +{ OPLOG, FORCC, + SAREG|SOREG|SNAME, TSHORT|TUSHORT, + SCON|SAREG, TANY, + 0, RESCC, + " cmpw AR,AL\n", }, + +{ OPLOG, FORCC, + SAREG|SOREG|SNAME, TCHAR|TUCHAR, + SCON|SAREG, TANY, + 0, RESCC, + " cmpb AR,AL\n", }, + +{ OPLOG, FORCC, + SBREG, TDOUBLE|TFLOAT, + SBREG|SNAME|SOREG, TDOUBLE|TFLOAT, + 0, RNOP, + " ucomisZg AR,AL\nZU\n", }, + +/* x87 */ +{ OPLOG, FORCC, + SCREG, TLDOUBLE, + SCREG, TLDOUBLE, + 0, RNOP, + "ZG", }, + +{ OPLOG, FORCC, + SANY, TANY, + SANY, TANY, + REWRITE, 0, + "diediedie!", }, + +/* AND/OR/ER/NOT */ +{ AND, INAREG|FOREFF, + SAREG|SOREG|SNAME, TLL, + SCON, TWORD, + 0, RLEFT, + " andq AR,AL\n", }, + +{ AND, INAREG|FOREFF, + SAREG|SOREG|SNAME, TLL, + SAREG, TLL, + 0, RLEFT, + " andq AR,AL\n", }, + +{ AND, INAREG|FOREFF, + SAREG, TLL, + SAREG|SOREG|SNAME, TLL, + 0, RLEFT, + " andq AR,AL\n", }, + +{ AND, INAREG|FOREFF, + SAREG|SOREG|SNAME, TWORD, + SCON|SAREG, TWORD, + 0, RLEFT, + " andl AR,AL\n", }, + +{ AND, INAREG|FOREFF, + SAREG, TWORD, + SAREG|SOREG|SNAME, TWORD, + 0, RLEFT, + " andl AR,AL\n", }, + +{ AND, INAREG|FOREFF, + SAREG|SOREG|SNAME, TSHORT|TUSHORT, + SCON|SAREG, TSHORT|TUSHORT, + 0, RLEFT, + " andw AR,AL\n", }, + +{ AND, INAREG|FOREFF, + SAREG, TSHORT|TUSHORT, + SAREG|SOREG|SNAME, TSHORT|TUSHORT, + 0, RLEFT, + " andw AR,AL\n", }, + +{ AND, INAREG|FOREFF, + SAREG|SOREG|SNAME, TCHAR|TUCHAR, + SCON|SAREG, TCHAR|TUCHAR, + 0, RLEFT, + " andb AR,AL\n", }, + +{ AND, INAREG|FOREFF, + SAREG, TCHAR|TUCHAR, + SAREG|SOREG|SNAME, TCHAR|TUCHAR, + 0, RLEFT, + " andb AR,AL\n", }, +/* AND/OR/ER/NOT */ + +/* + * Jumps. + */ +{ GOTO, FOREFF, + SCON, TANY, + SANY, TANY, + 0, RNOP, + " jmp LL\n", }, + +#if defined(GCC_COMPAT) || defined(LANG_F77) +{ GOTO, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, RNOP, + " jmp *AL\n", }, +#endif + +/* + * Convert LTYPE to reg. + */ +{ OPLTYPE, FORCC|INAREG, + SAREG, TLL|TPOINT, + SMIXOR, TANY, + NAREG, RESC1, + " xorq A1,A1\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SAREG|SCON|SOREG|SNAME, TLL|TPOINT, + NAREG, RESC1, + " movq AL,A1\n", }, + +{ OPLTYPE, FORCC|INAREG, + SAREG, TWORD, + SMIXOR, TANY, + NAREG|NASL, RESC1, + " xorl A1,A1\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SAREG|SCON|SOREG|SNAME, TWORD, + NAREG|NASL, RESC1, + " movl AL,A1\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SAREG|SOREG|SNAME|SCON, TCHAR|TUCHAR, + NAREG, RESC1, + " movb AL,A1\n", }, + +{ OPLTYPE, FORCC|INAREG, + SAREG, TSHORT|TUSHORT, + SMIXOR, TANY, + NAREG, RESC1, + " xorw A1,A1\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SAREG|SOREG|SNAME|SCON, TSHORT|TUSHORT, + NAREG, RESC1, + " movw AL,A1\n", }, + +{ OPLTYPE, INBREG, + SANY, TFLOAT|TDOUBLE, + SOREG|SNAME|SBREG, TFLOAT|TDOUBLE, + NBREG, RESC1, + " movsZf AL,A1\n", }, + +/* x87 entry */ +{ OPLTYPE, INCREG, + SANY, TLDOUBLE, + SOREG|SNAME, TLDOUBLE, + NCREG, RESC1, + " fldt AL\n", }, + +/* + * Negate a word. + */ + +{ UMINUS, INAREG|FOREFF, + SAREG, TLL|TPOINT, + SAREG, TLL|TPOINT, + 0, RLEFT, + " negq AL\n", }, + +{ UMINUS, INAREG|FOREFF, + SAREG, TWORD, + SAREG, TWORD, + 0, RLEFT, + " negl AL\n", }, + +{ UMINUS, INAREG|FOREFF, + SAREG, TSHORT|TUSHORT, + SAREG, TSHORT|TUSHORT, + 0, RLEFT, + " negw AL\n", }, + +{ UMINUS, INAREG|FOREFF, + SAREG, TCHAR|TUCHAR, + SAREG, TCHAR|TUCHAR, + 0, RLEFT, + " negb AL\n", }, + +{ UMINUS, INBREG, + SBREG, TDOUBLE|TFLOAT, + SBREG, TDOUBLE|TFLOAT, + 0, RLEFT, + " xorpZf LC(%rip),AL\n", }, + +{ UMINUS, INCREG, + SCREG, TLDOUBLE, + SCREG, TLDOUBLE, + 0, RLEFT, + " fchs\n", }, + +{ COMPL, INAREG, + SAREG, TLL, + SANY, TANY, + 0, RLEFT, + " notq AL\n", }, + +{ COMPL, INAREG, + SAREG, TWORD, + SANY, TANY, + 0, RLEFT, + " notl AL\n", }, + +{ COMPL, INAREG, + SAREG, TSHORT|TUSHORT, + SANY, TANY, + 0, RLEFT, + " notw AL\n", }, + +{ COMPL, INAREG, + SAREG, TCHAR|TUCHAR, + SANY, TANY, + 0, RLEFT, + " notb AL\n", }, + +{ STARG, FOREFF, + SAREG|SOREG|SNAME|SCON, TANY, + SANY, TSTRUCT, + NSPECIAL, 0, + "ZF", }, + +{ ADDROF, INAREG, + SNAME, TANY, + SANY, TANY, + NAREG, RESC1, + " leaq AL,A1\n", }, + +# define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,"" + +{ UMUL, DF( UMUL ), }, + +{ ASSIGN, DF(ASSIGN), }, + +{ STASG, DF(STASG), }, + +{ FLD, DF(FLD), }, + +{ OPLEAF, DF(NAME), }, + +/* { INIT, DF(INIT), }, */ + +{ OPUNARY, DF(UMINUS), }, + +{ OPANY, DF(BITYPE), }, + +{ FREE, FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" }, +}; + +int tablesize = sizeof(table)/sizeof(table[0]); diff --git a/compilers/pcc/pcc-1.0.0/arch/arm/CVS/Entries b/compilers/pcc/pcc-1.0.0/arch/arm/CVS/Entries new file mode 100644 index 00000000..d765adba --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/arm/CVS/Entries @@ -0,0 +1,7 @@ +/code.c/1.21/Sun Feb 8 16:07:52 2009//Tr-1-0-0-RELEASE +/local.c/1.24/Fri Jan 21 21:47:58 2011//Tr-1-0-0-RELEASE +/local2.c/1.34/Sun Dec 14 21:16:58 2008//Tr-1-0-0-RELEASE +/macdefs.h/1.12/Sat Jan 24 21:43:48 2009//Tr-1-0-0-RELEASE +/order.c/1.9/Sat Sep 27 07:35:22 2008//Tr-1-0-0-RELEASE +/table.c/1.19/Fri May 16 02:20:36 2008//Tr-1-0-0-RELEASE +D diff --git a/compilers/pcc/pcc-1.0.0/arch/arm/CVS/Repository b/compilers/pcc/pcc-1.0.0/arch/arm/CVS/Repository new file mode 100644 index 00000000..6ee0366e --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/arm/CVS/Repository @@ -0,0 +1 @@ +pcc/arch/arm diff --git a/compilers/pcc/pcc-1.0.0/arch/arm/CVS/Root b/compilers/pcc/pcc-1.0.0/arch/arm/CVS/Root new file mode 100644 index 00000000..71e2ccb9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/arm/CVS/Root @@ -0,0 +1 @@ +/cvsroot diff --git a/compilers/pcc/pcc-1.0.0/arch/arm/CVS/Tag b/compilers/pcc/pcc-1.0.0/arch/arm/CVS/Tag new file mode 100644 index 00000000..060fac05 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/arm/CVS/Tag @@ -0,0 +1 @@ +Nr-1-0-0-RELEASE diff --git a/compilers/pcc/pcc-1.0.0/arch/arm/code.c b/compilers/pcc/pcc-1.0.0/arch/arm/code.c new file mode 100644 index 00000000..407548fe --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/arm/code.c @@ -0,0 +1,889 @@ +/* $Id: code.c,v 1.21 2009/02/08 16:07:52 ragge Exp $ */ +/* + * Copyright (c) 2007 Gregory McGarry (g.mcgarry@ieee.org). + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Stuff for pass1. + */ + +#include + +#include "pass1.h" +#include "pass2.h" + +int lastloc = -1; +static int rvnr; + +/* + * Define everything needed to print out some data (or text). + * This means segment, alignment, visibility, etc. + */ +void +defloc(struct symtab *sp) +{ + extern char *nextsect; + static char *loctbl[] = { "text", "data", "section .rodata" }; + char *n; + TWORD t; + int s; + + if (sp == NULL) { + lastloc = -1; + return; + } + t = sp->stype; + s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? PROG : DATA; + if (nextsect) { + printf("\t.section %s\n", nextsect); + nextsect = NULL; + s = -1; + } else if (s != lastloc) + printf("\t.%s\n", loctbl[s]); + lastloc = s; + while (ISARY(t)) + t = DECREF(t); + if (t > UCHAR) + printf("\t.align %d\n", t > USHORT ? 4 : 2); + n = sp->soname ? sp->soname : exname(sp->sname); +#ifdef USE_GAS + if (ISFTN(t)) + printf("\t.type %s,%%function\n", n); +#endif + if (sp->sclass == EXTDEF) + printf("\t.global %s\n", n); + if (ISFTN(t)) + return; + if (sp->slevel == 0) + printf("%s:\n", n); + else + printf(LABFMT ":\n", sp->soffset); +} + +/* Put a symbol in a temporary + * used by bfcode() and its helpers + */ +static void +putintemp(struct symtab *sym) +{ + NODE *p; + + p = tempnode(0, sym->stype, sym->sdf, sym->ssue); + p = buildtree(ASSIGN, p, nametree(sym)); + sym->soffset = regno(p->n_left); + sym->sflags |= STNODE; + ecomp(p); +} + +/* setup a 64-bit parameter (double/ldouble/longlong) + * used by bfcode() */ +static void +param_64bit(struct symtab *sym, int *argofsp, int dotemps) +{ + int argofs = *argofsp; + NODE *p, *q; + int navail; + +#if ALLONGLONG == 64 + /* alignment */ + ++argofs; + argofs &= ~1; + *argofsp = argofs; +#endif + + navail = NARGREGS - argofs; + + if (navail < 2) { + /* half in and half out of the registers */ + if (features(FEATURE_BIGENDIAN)) { + cerror("param_64bit"); + p = q = NULL; + } else { + q = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(q) = R0 + argofs; + if (dotemps) { + q = block(SCONV, q, NIL, + ULONGLONG, 0, MKSUE(ULONGLONG)); + p = nametree(sym); + p->n_type = ULONGLONG; + p->n_df = 0; + p->n_sue = MKSUE(ULONGLONG); + p = block(LS, p, bcon(32), ULONGLONG, + 0, MKSUE(ULONGLONG)); + q = block(PLUS, p, q, ULONGLONG, + 0, MKSUE(ULONGLONG)); + p = tempnode(0, ULONGLONG, + 0, MKSUE(ULONGLONG)); + sym->soffset = regno(p); + sym->sflags |= STNODE; + } else { + p = nametree(sym); + regno(p) = sym->soffset; + p->n_type = INT; + p->n_df = 0; + p->n_sue = MKSUE(INT); + } + } + p = buildtree(ASSIGN, p, q); + ecomp(p); + *argofsp = argofs + 2; + return; + } + + q = block(REG, NIL, NIL, sym->stype, sym->sdf, sym->ssue); + regno(q) = R0R1 + argofs; + if (dotemps) { + p = tempnode(0, sym->stype, sym->sdf, sym->ssue); + sym->soffset = regno(p); + sym->sflags |= STNODE; + } else { + p = nametree(sym); + } + p = buildtree(ASSIGN, p, q); + ecomp(p); + *argofsp = argofs + 2; +} + +/* setup a 32-bit param on the stack + * used by bfcode() */ +static void +param_32bit(struct symtab *sym, int *argofsp, int dotemps) +{ + NODE *p, *q; + + q = block(REG, NIL, NIL, sym->stype, sym->sdf, sym->ssue); + regno(q) = R0 + (*argofsp)++; + if (dotemps) { + p = tempnode(0, sym->stype, sym->sdf, sym->ssue); + sym->soffset = regno(p); + sym->sflags |= STNODE; + } else { + p = nametree(sym); + } + p = buildtree(ASSIGN, p, q); + ecomp(p); +} + +/* setup a double param on the stack + * used by bfcode() */ +static void +param_double(struct symtab *sym, int *argofsp, int dotemps) +{ + NODE *p, *q, *t; + int tmpnr; + + /* + * we have to dump the float from the general register + * into a temp, since the register allocator doesn't like + * floats to be in CLASSA. This may not work for -xtemps. + */ + + t = tempnode(0, ULONGLONG, 0, MKSUE(ULONGLONG)); + tmpnr = regno(t); + q = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + q->n_rval = R0R1 + (*argofsp)++; + p = buildtree(ASSIGN, t, q); + ecomp(p); + + if (dotemps) { + sym->soffset = tmpnr; + sym->sflags |= STNODE; + } else { + q = tempnode(tmpnr, sym->stype, sym->sdf, sym->ssue); + p = nametree(sym); + p = buildtree(ASSIGN, p, q); + ecomp(p); + } +} + +/* setup a float param on the stack + * used by bfcode() */ +static void +param_float(struct symtab *sym, int *argofsp, int dotemps) +{ + NODE *p, *q, *t; + int tmpnr; + + /* + * we have to dump the float from the general register + * into a temp, since the register allocator doesn't like + * floats to be in CLASSA. This may not work for -xtemps. + */ + + t = tempnode(0, INT, 0, MKSUE(INT)); + tmpnr = regno(t); + q = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + q->n_rval = R0 + (*argofsp)++; + p = buildtree(ASSIGN, t, q); + ecomp(p); + + if (dotemps) { + sym->soffset = tmpnr; + sym->sflags |= STNODE; + } else { + q = tempnode(tmpnr, sym->stype, sym->sdf, sym->ssue); + p = nametree(sym); + p = buildtree(ASSIGN, p, q); + ecomp(p); + } +} + +/* setup the hidden pointer to struct return parameter + * used by bfcode() */ +static void +param_retstruct(void) +{ + NODE *p, *q; + + p = tempnode(0, PTR-FTN+cftnsp->stype, 0, cftnsp->ssue); + rvnr = regno(p); + q = block(REG, NIL, NIL, PTR+STRTY, 0, cftnsp->ssue); + regno(q) = R0; + p = buildtree(ASSIGN, p, q); + ecomp(p); +} + + +/* setup struct parameter + * push the registers out to memory + * used by bfcode() */ +static void +param_struct(struct symtab *sym, int *argofsp) +{ + int argofs = *argofsp; + NODE *p, *q; + int navail; + int sz; + int off; + int num; + int i; + + navail = NARGREGS - argofs; + sz = tsize(sym->stype, sym->sdf, sym->ssue) / SZINT; + off = ARGINIT/SZINT + argofs; + num = sz > navail ? navail : sz; + for (i = 0; i < num; i++) { + q = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(q) = R0 + argofs++; + p = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(p) = SP; + p = block(PLUS, p, bcon(4*off++), INT, 0, MKSUE(INT)); + p = block(UMUL, p, NIL, INT, 0, MKSUE(INT)); + p = buildtree(ASSIGN, p, q); + ecomp(p); + } + + *argofsp = argofs; +} + + +/* + * Beginning-of-function code: + * + * 'sp' is an array of indices in symtab for the arguments + * 'cnt' is the number of arguments + */ +void +bfcode(struct symtab **sp, int cnt) +{ + union arglist *usym; + int saveallargs = 0; + int i, argofs = 0; + + /* + * Detect if this function has ellipses and save all + * argument registers onto stack. + */ + usym = cftnsp->sdf->dfun; + while (usym && usym->type != TNULL) { + if (usym->type == TELLIPSIS) { + saveallargs = 1; + break; + } + ++usym; + } + + /* if returning a structure, move the hidden argument into a TEMP */ + if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) { + param_retstruct(); + ++argofs; + } + + /* recalculate the arg offset and create TEMP moves */ + for (i = 0; i < cnt; i++) { + + if (sp[i] == NULL) + continue; + + if ((argofs >= NARGREGS) && !xtemps) + break; + + if (argofs > NARGREGS) { + putintemp(sp[i]); + } else if (sp[i]->stype == STRTY || sp[i]->stype == UNIONTY) { + param_struct(sp[i], &argofs); + } else if (DEUNSIGN(sp[i]->stype) == LONGLONG) { + param_64bit(sp[i], &argofs, xtemps && !saveallargs); + } else if (sp[i]->stype == DOUBLE || sp[i]->stype == LDOUBLE) { + if (features(FEATURE_HARDFLOAT)) + param_double(sp[i], &argofs, + xtemps && !saveallargs); + else + param_64bit(sp[i], &argofs, + xtemps && !saveallargs); + } else if (sp[i]->stype == FLOAT) { + if (features(FEATURE_HARDFLOAT)) + param_float(sp[i], &argofs, + xtemps && !saveallargs); + else + param_32bit(sp[i], &argofs, + xtemps && !saveallargs); + } else { + param_32bit(sp[i], &argofs, xtemps && !saveallargs); + } + } + + /* if saveallargs, save the rest of the args onto the stack */ + while (saveallargs && argofs < NARGREGS) { + NODE *p, *q; + int off = ARGINIT/SZINT + argofs; + q = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(q) = R0 + argofs++; + p = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(p) = FPREG; + p = block(PLUS, p, bcon(4*off), INT, 0, MKSUE(INT)); + p = block(UMUL, p, NIL, INT, 0, MKSUE(INT)); + p = buildtree(ASSIGN, p, q); + ecomp(p); + } + +} + +/* + * End-of-Function code: + */ +void +efcode() +{ + NODE *p, *q; + int tempnr; + + if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) + return; + + /* + * At this point, the address of the return structure on + * has been FORCEd to RETREG, which is R0. + * We want to copy the contents from there to the address + * we placed into the tempnode "rvnr". + */ + + /* move the pointer out of R0 to a tempnode */ + q = block(REG, NIL, NIL, PTR+STRTY, 0, cftnsp->ssue); + q->n_rval = R0; + p = tempnode(0, PTR+STRTY, 0, cftnsp->ssue); + tempnr = regno(p); + p = buildtree(ASSIGN, p, q); + ecomp(p); + + /* get the address from the tempnode */ + q = tempnode(tempnr, PTR+STRTY, 0, cftnsp->ssue); + q = buildtree(UMUL, q, NIL); + + /* now, get the structure destination */ + p = tempnode(rvnr, PTR+STRTY, 0, cftnsp->ssue); + p = buildtree(UMUL, p, NIL); + + /* struct assignment */ + p = buildtree(ASSIGN, p, q); + ecomp(p); +} + +/* + * Beginning-of-code: finished generating function prologue + * + * by now, the automatics and register variables are allocated + */ +void +bccode() +{ + SETOFF(autooff, SZINT); +} + +/* + * End-of-job: called just before final exit. + */ +void +ejobcode(int flag ) +{ +#define _MKSTR(x) #x +#define MKSTR(x) _MKSTR(x) +#define OS MKSTR(TARGOS) + printf("\t.ident \"PCC: %s (%s)\"\n", PACKAGE_STRING, OS); +} + +/* + * Beginning-of-job: called before compilation starts + * + * Initialise data structures specific for the local machine. + */ +void +bjobcode() +{ +} + +/* + * Compute the alignment of object with type 't'. + */ +int +fldal(unsigned int t) +{ + uerror("illegal field type"); + return(ALINT); +} + +/* + * fix up type of field p + */ +void +fldty(struct symtab *p) +{ +} + +/* + * Build target-dependent switch tree/table. + * + * Return 1 if successfull, otherwise return 0 and the + * target-independent tree will be used. + */ +int +mygenswitch(int num, TWORD type, struct swents **p, int n) +{ + return 0; +} + + +/* + * Straighten a chain of CM ops so that the CM nodes + * only appear on the left node. + * + * CM CM + * CM CM CM b + * x y a b CM a + * x y + */ +static NODE * +straighten(NODE *p) +{ + NODE *r = p->n_right; + + if (p->n_op != CM || r->n_op != CM) + return p; + + p->n_right = r->n_left; + r->n_left = p; + + return r; +} + +static NODE * +reverse1(NODE *p, NODE *a) +{ + NODE *l = p->n_left; + NODE *r = p->n_right; + + a->n_right = r; + p->n_left = a; + + if (l->n_op == CM) { + return reverse1(l, p); + } else { + p->n_right = l; + return p; + } +} + +/* + * Reverse a chain of CM ops + */ +static NODE * +reverse(NODE *p) +{ + NODE *l = p->n_left; + NODE *r = p->n_right; + + p->n_left = r; + + if (l->n_op == CM) + return reverse1(l, p); + + p->n_right = l; + + return p; +} + + +/* push arg onto the stack */ +/* called by moveargs() */ +static NODE * +pusharg(NODE *p, int *regp) +{ + NODE *q; + int sz; + + /* convert to register size, if smaller */ + sz = tsize(p->n_type, p->n_df, p->n_sue); + if (sz < SZINT) + p = block(SCONV, p, NIL, INT, 0, MKSUE(INT)); + + q = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(q) = SP; + + if (szty(p->n_type) == 1) { + ++(*regp); + q = block(MINUSEQ, q, bcon(4), INT, 0, MKSUE(INT)); + } else { + (*regp) += 2; + q = block(MINUSEQ, q, bcon(8), INT, 0, MKSUE(INT)); + } + + q = block(UMUL, q, NIL, p->n_type, p->n_df, p->n_sue); + + return buildtree(ASSIGN, q, p); +} + +/* setup call stack with 32-bit argument */ +/* called from moveargs() */ +static NODE * +movearg_32bit(NODE *p, int *regp) +{ + int reg = *regp; + NODE *q; + + q = block(REG, NIL, NIL, p->n_type, p->n_df, p->n_sue); + regno(q) = reg++; + q = buildtree(ASSIGN, q, p); + + *regp = reg; + return q; +} + +/* setup call stack with 64-bit argument */ +/* called from moveargs() */ +static NODE * +movearg_64bit(NODE *p, int *regp) +{ + int reg = *regp; + NODE *q, *r; + +#if ALLONGLONG == 64 + /* alignment */ + ++reg; + reg &= ~1; + *regp = reg; +#endif + + if (reg > R3) { + q = pusharg(p, regp); + } else if (reg == R3) { + /* half in and half out of the registers */ + r = tcopy(p); + if (!features(FEATURE_BIGENDIAN)) { + q = block(SCONV, p, NIL, INT, 0, MKSUE(INT)); + q = movearg_32bit(q, regp); /* little-endian */ + r = buildtree(RS, r, bcon(32)); + r = block(SCONV, r, NIL, INT, 0, MKSUE(INT)); + r = pusharg(r, regp); /* little-endian */ + } else { + q = buildtree(RS, p, bcon(32)); + q = block(SCONV, q, NIL, INT, 0, MKSUE(INT)); + q = movearg_32bit(q, regp); /* big-endian */ + r = block(SCONV, r, NIL, INT, 0, MKSUE(INT)); + r = pusharg(r, regp); /* big-endian */ + } + q = straighten(block(CM, q, r, p->n_type, p->n_df, p->n_sue)); + } else { + q = block(REG, NIL, NIL, p->n_type, p->n_df, p->n_sue); + regno(q) = R0R1 + (reg - R0); + q = buildtree(ASSIGN, q, p); + *regp = reg + 2; + } + + return q; +} + +/* setup call stack with float/double argument */ +/* called from moveargs() */ +static NODE * +movearg_float(NODE *p, int *regp) +{ + NODE *q, *r; + TWORD ty = INCREF(p->n_type); + int tmpnr; + + /* + * Floats are passed in the general registers for + * compatibily with libraries compiled to handle soft-float. + */ + + if (xtemps) { + /* bounce on TOS */ + r = block(REG, NIL, NIL, ty, p->n_df, p->n_sue); + regno(r) = SP; + r = block(PLUS, r, bcon(-4), ty, p->n_df, p->n_sue); + r = block(UMUL, r, NIL, p->n_type, p->n_df, p->n_sue); + r = buildtree(ASSIGN, r, p); + ecomp(r); + + /* bounce into temp */ + r = block(REG, NIL, NIL, PTR+INT, 0, MKSUE(INT)); + regno(r) = SP; + r = block(PLUS, r, bcon(-8), PTR+INT, 0, MKSUE(INT)); + r = block(UMUL, r, NIL, INT, 0, MKSUE(INT)); + q = tempnode(0, INT, 0, MKSUE(INT)); + tmpnr = regno(q); + r = buildtree(ASSIGN, q, r); + ecomp(r); + } else { + /* copy directly into temp */ + q = tempnode(0, p->n_type, p->n_df, p->n_sue); + tmpnr = regno(q); + r = buildtree(ASSIGN, q, p); + ecomp(r); + } + + /* copy from temp to register parameter */ + r = tempnode(tmpnr, INT, 0, MKSUE(INT)); + q = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(q) = (*regp)++; + p = buildtree(ASSIGN, q, r); + + return p; +} + +/* setup call stack with float/double argument */ +/* called from moveargs() */ +static NODE * +movearg_double(NODE *p, int *regp) +{ + NODE *q, *r; + TWORD ty = INCREF(p->n_type); + int tmpnr; + + if (xtemps) { + /* bounce on TOS */ + r = block(REG, NIL, NIL, ty, p->n_df, p->n_sue); + regno(r) = SP; + r = block(PLUS, r, bcon(-8), ty, p->n_df, p->n_sue); + r = block(UMUL, r, NIL, p->n_type, p->n_df, p->n_sue); + r = buildtree(ASSIGN, r, p); + ecomp(r); + + /* bounce into temp */ + r = block(REG, NIL, NIL, PTR+LONGLONG, 0, MKSUE(LONGLONG)); + regno(r) = SP; + r = block(PLUS, r, bcon(-8), PTR+LONGLONG, 0, MKSUE(LONGLONG)); + r = block(UMUL, r, NIL, LONGLONG, 0, MKSUE(LONGLONG)); + q = tempnode(0, LONGLONG, 0, MKSUE(LONGLONG)); + tmpnr = regno(q); + r = buildtree(ASSIGN, q, r); + ecomp(r); + } else { + /* copy directly into temp */ + q = tempnode(0, p->n_type, p->n_df, p->n_sue); + tmpnr = regno(q); + r = buildtree(ASSIGN, q, p); + ecomp(r); + } + + /* copy from temp to register parameter */ + r = tempnode(tmpnr, LONGLONG, 0, MKSUE(LONGLONG)); + q = block(REG, NIL, NIL, LONGLONG, 0, MKSUE(LONGLONG)); + regno(q) = R0R1 - R0 + (*regp); + p = buildtree(ASSIGN, q, r); + + (*regp) += 2; + + return p; +} + + +/* setup call stack with a structure */ +/* called from moveargs() */ +static NODE * +movearg_struct(NODE *p, int *regp) +{ + int reg = *regp; + NODE *l, *q, *t, *r; + int tmpnr; + int navail; + int num; + int sz; + int ty; + int i; + + assert(p->n_op == STARG); + + navail = NARGREGS - (reg - R0); + navail = navail < 0 ? 0 : navail; + sz = tsize(p->n_type, p->n_df, p->n_sue) / SZINT; + num = sz > navail ? navail : sz; + + /* remove STARG node */ + l = p->n_left; + nfree(p); + ty = l->n_type; + + /* + * put it into a TEMP, rather than tcopy(), since the tree + * in p may have side-affects + */ + t = tempnode(0, ty, l->n_df, l->n_sue); + tmpnr = regno(t); + q = buildtree(ASSIGN, t, l); + + /* copy structure into registers */ + for (i = 0; i < num; i++) { + t = tempnode(tmpnr, ty, 0, MKSUE(PTR+ty)); + t = block(SCONV, t, NIL, PTR+INT, 0, MKSUE(PTR+INT)); + t = block(PLUS, t, bcon(4*i), PTR+INT, 0, MKSUE(PTR+INT)); + t = buildtree(UMUL, t, NIL); + + r = block(REG, NIL, NIL, INT, 0, MKSUE(INT)); + regno(r) = reg++; + r = buildtree(ASSIGN, r, t); + + q = block(CM, q, r, INT, 0, MKSUE(INT)); + } + + /* put the rest of the structure on the stack */ + for (i = num; i < sz; i++) { + t = tempnode(tmpnr, ty, 0, MKSUE(PTR+ty)); + t = block(SCONV, t, NIL, PTR+INT, 0, MKSUE(PTR+INT)); + t = block(PLUS, t, bcon(4*i), PTR+INT, 0, MKSUE(PTR+INT)); + t = buildtree(UMUL, t, NIL); + r = pusharg(t, ®); + q = block(CM, q, r, INT, 0, MKSUE(INT)); + } + + q = reverse(q); + + *regp = reg; + return q; +} + + +static NODE * +moveargs(NODE *p, int *regp) +{ + NODE *r, **rp; + int reg; + + if (p->n_op == CM) { + p->n_left = moveargs(p->n_left, regp); + r = p->n_right; + rp = &p->n_right; + } else { + r = p; + rp = &p; + } + + reg = *regp; + + if (reg > R3 && r->n_op != STARG) { + *rp = pusharg(r, regp); + } else if (r->n_op == STARG) { + *rp = movearg_struct(r, regp); + } else if (DEUNSIGN(r->n_type) == LONGLONG) { + *rp = movearg_64bit(r, regp); + } else if (r->n_type == DOUBLE || r->n_type == LDOUBLE) { + *rp = movearg_double(r, regp); + } else if (r->n_type == FLOAT) { + *rp = movearg_float(r, regp); + } else { + *rp = movearg_32bit(r, regp); + } + + return straighten(p); +} + +/* + * Fixup arguments to pass pointer-to-struct as first argument. + * + * called from funcode(). + */ +static NODE * +retstruct(NODE *p) +{ + NODE *l, *r, *t, *q; + TWORD ty; + + l = p->n_left; + r = p->n_right; + + ty = DECREF(l->n_type) - FTN; + +// assert(tsize(ty, l->n_df, l->n_sue) == SZINT); + + /* structure assign */ + q = tempnode(0, ty, l->n_df, l->n_sue); + q = buildtree(ADDROF, q, NIL); + + /* insert hidden assignment at beginning of list */ + if (r->n_op != CM) { + p->n_right = block(CM, q, r, INCREF(ty), l->n_df, l->n_sue); + } else { + for (t = r; t->n_left->n_op == CM; t = t->n_left) + ; + t->n_left = block(CM, q, t->n_left, INCREF(ty), + l->n_df, l->n_sue); + } + + return p; +} + +/* + * Called with a function call with arguments as argument. + * This is done early in buildtree() and only done once. + */ +NODE * +funcode(NODE *p) +{ + int reg = R0; + + if (p->n_type == STRTY+FTN || p->n_type == UNIONTY+FTN) { + p = retstruct(p); + reg = R1; + } + + p->n_right = moveargs(p->n_right, ®); + + if (p->n_right == NULL) + p->n_op += (UCALL - CALL); + + return p; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/arm/local.c b/compilers/pcc/pcc-1.0.0/arch/arm/local.c new file mode 100644 index 00000000..185c1f9c --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/arm/local.c @@ -0,0 +1,816 @@ +/* $Id: local.c,v 1.24 2011/01/21 21:47:58 ragge Exp $ */ +/* + * Copyright (c) 2007 Gregory McGarry (g.mcgarry@ieee.org). + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * We define location operations which operate on the expression tree + * during the first pass (before sending to the backend for code generation.) + */ + +#include + +#include "pass1.h" + +extern void defalign(int); + +/* + * clocal() is called to do local transformations on + * an expression tree before being sent to the backend. + */ +NODE * +clocal(NODE *p) +{ + struct symtab *q; + NODE *l, *r, *t; + int o; + int ty; + int tmpnr, isptrvoid = 0; + char *n; + + o = p->n_op; + switch (o) { + + case STASG: + + l = p->n_left; + r = p->n_right; + if (r->n_op != STCALL && r->n_op != USTCALL) + return p; + + /* assign left node as first argument to function */ + nfree(p); + t = block(REG, NIL, NIL, r->n_type, r->n_df, r->n_sue); + l->n_rval = R0; + l = buildtree(ADDROF, l, NIL); + l = buildtree(ASSIGN, t, l); + + if (r->n_right->n_op != CM) { + r->n_right = block(CM, l, r->n_right, + INT, 0, MKSUE(INT)); + } else { + for (t = r->n_right; t->n_left->n_op == CM; + t = t->n_left) + ; + t->n_left = block(CM, l, t->n_left, + INT, 0, MKSUE(INT)); + } + return r; + + case CALL: + case STCALL: + case USTCALL: + if (p->n_type == VOID) + break; + /* + * if the function returns void*, ecode() invokes + * delvoid() to convert it to uchar*. + * We just let this happen on the ASSIGN to the temp, + * and cast the pointer back to void* on access + * from the temp. + */ + if (p->n_type == PTR+VOID) + isptrvoid = 1; + r = tempnode(0, p->n_type, p->n_df, p->n_sue); + tmpnr = regno(r); + r = block(ASSIGN, r, p, p->n_type, p->n_df, p->n_sue); + + p = tempnode(tmpnr, r->n_type, r->n_df, r->n_sue); + if (isptrvoid) { + p = block(PCONV, p, NIL, PTR+VOID, + p->n_df, MKSUE(PTR+VOID)); + } + p = buildtree(COMOP, r, p); + break; + + case NAME: + if ((q = p->n_sp) == NULL) + return p; + if (blevel == 0) + return p; + + switch (q->sclass) { + case PARAM: + case AUTO: + /* fake up a structure reference */ + r = block(REG, NIL, NIL, PTR+STRTY, 0, 0); + r->n_lval = 0; + r->n_rval = FPREG; + p = stref(block(STREF, r, p, 0, 0, 0)); + break; + case REGISTER: + p->n_op = REG; + p->n_lval = 0; + p->n_rval = q->soffset; + break; + case STATIC: + if (q->slevel > 0) { + p->n_lval = 0; + p->n_sp = q; + } + /* FALL-THROUGH */ + default: + ty = p->n_type; + n = p->n_sp->soname ? p->n_sp->soname : p->n_sp->sname; + if (strncmp(n, "__builtin", 9) == 0) + break; + p = block(ADDROF, p, NIL, INCREF(ty), p->n_df, p->n_sue); + p = block(UMUL, p, NIL, ty, p->n_df, p->n_sue); + break; + } + break; + + case STNAME: + if ((q = p->n_sp) == NULL) + return p; + if (q->sclass != STNAME) + return p; + ty = p->n_type; + p = block(ADDROF, p, NIL, INCREF(ty), + p->n_df, p->n_sue); + p = block(UMUL, p, NIL, ty, p->n_df, p->n_sue); + break; + + case FORCE: + /* put return value in return reg */ + p->n_op = ASSIGN; + p->n_right = p->n_left; + p->n_left = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT)); + p->n_left->n_rval = p->n_left->n_type == BOOL ? + RETREG(BOOL_TYPE) : RETREG(p->n_type); + break; + + case PMCONV: + case PVCONV: + nfree(p); + return buildtree(o == PMCONV ? MUL : DIV, p->n_left, p->n_right); + + case SCONV: + l = p->n_left; + if (p->n_type == l->n_type) { + nfree(p); + return l; + } + if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 && + btdims[p->n_type].suesize == btdims[l->n_type].suesize) { + if (p->n_type != FLOAT && p->n_type != DOUBLE && + l->n_type != FLOAT && l->n_type != DOUBLE && + l->n_type != LDOUBLE && p->n_type != LDOUBLE) { + if (l->n_op == NAME || l->n_op == UMUL || + l->n_op == TEMP) { + l->n_type = p->n_type; + nfree(p); + return l; + } + } + } + + if (l->n_op == ICON) { + CONSZ val = l->n_lval; + + if (!ISPTR(p->n_type)) /* Pointers don't need to be conv'd */ + switch (p->n_type) { + case BOOL: + l->n_lval = l->n_lval != 0; + break; + case CHAR: + l->n_lval = (char)val; + break; + case UCHAR: + l->n_lval = val & 0377; + break; + case SHORT: + l->n_lval = (short)val; + break; + case USHORT: + l->n_lval = val & 0177777; + break; + case ULONG: + case UNSIGNED: + l->n_lval = val & 0xffffffff; + break; + case LONG: + case INT: + l->n_lval = (int)val; + break; + case LONGLONG: + l->n_lval = (long long)val; + break; + case ULONGLONG: + l->n_lval = val; + break; + case VOID: + break; + case LDOUBLE: + case DOUBLE: + case FLOAT: + l->n_op = FCON; + l->n_dcon = val; + break; + default: + cerror("unknown type %d", l->n_type); + } + l->n_type = p->n_type; + l->n_sue = MKSUE(p->n_type); + nfree(p); + return l; + } else if (p->n_op == FCON) { + l->n_lval = l->n_dcon; + l->n_sp = NULL; + l->n_op = ICON; + l->n_type = p->n_type; + l->n_sue = MKSUE(p->n_type); + nfree(p); + return clocal(l); + } + if ((DEUNSIGN(p->n_type) == CHAR || + DEUNSIGN(p->n_type) == SHORT) && + (l->n_type == FLOAT || l->n_type == DOUBLE || + l->n_type == LDOUBLE)) { + p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_sue); + p->n_left->n_type = INT; + return p; + } + break; + + case PCONV: + l = p->n_left; + if (l->n_op == ICON) { + l->n_lval = (unsigned)l->n_lval; + goto delp; + } + if (l->n_type < INT || DEUNSIGN(l->n_type) == LONGLONG) { + p->n_left = block(SCONV, l, NIL, + UNSIGNED, 0, MKSUE(UNSIGNED)); + break; + } + if (l->n_op == SCONV) + break; + if (l->n_op == ADDROF && l->n_left->n_op == TEMP) + goto delp; + if (p->n_type > BTMASK && l->n_type > BTMASK) + goto delp; + break; + + delp: + l->n_type = p->n_type; + l->n_qual = p->n_qual; + l->n_df = p->n_df; + l->n_sue = p->n_sue; + nfree(p); + p = l; + break; + } + + return p; +} + +/* + * Called before sending the tree to the backend. + */ +void +myp2tree(NODE *p) +{ + struct symtab *sp; + + if (p->n_op != FCON) + return; + +#define IALLOC(sz) (isinlining ? permalloc(sz) : tmpalloc(sz)) + + sp = IALLOC(sizeof(struct symtab)); + sp->sclass = STATIC; + sp->ssue = MKSUE(p->n_type); + sp->slevel = 1; /* fake numeric label */ + sp->soffset = getlab(); + sp->sflags = 0; + sp->stype = p->n_type; + sp->squal = (CON >> TSHIFT); + + defloc(sp); + ninval(0, sp->ssue->suesize, p); + + p->n_op = NAME; + p->n_lval = 0; + p->n_sp = sp; + +} + +/* + * Called during the first pass to determine if a NAME can be addressed. + * + * Return nonzero if supported, otherwise return 0. + */ +int +andable(NODE *p) +{ + if (blevel == 0) + return 1; + if (ISFTN(p->n_type)) + return 1; + return 0; +} + +/* + * Called just after function arguments are built. Re-initialize the + * offset of the arguments on the stack. + * Is this necessary anymore? bfcode() is called immediately after. + */ +void +cendarg() +{ + autooff = AUTOINIT; +} + +/* + * Return 1 if a variable of type 't' is OK to put in register. + */ +int +cisreg(TWORD t) +{ + if (t == FLOAT || t == DOUBLE || t == LDOUBLE) + return 0; /* not yet */ + return 1; +} + +/* + * Used for generating pointer offsets into structures and arrays. + * + * For a pointer of type 't', generate an the offset 'off'. + */ +NODE * +offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue) +{ + return bcon(off/SZCHAR); +} + +/* + * Allocate bits from the stack for dynamic-sized arrays. + * + * 'p' is the tree which represents the type being allocated. + * 'off' is the number of 'p's to be allocated. + * 't' is the storeable node where the address is written. + */ +void +spalloc(NODE *t, NODE *p, OFFSZ off) +{ + NODE *sp; + + p = buildtree(MUL, p, bcon(off/SZCHAR)); /* XXX word alignment? */ + + /* sub the size from sp */ + sp = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT)); + sp->n_lval = 0; + sp->n_rval = SP; + ecomp(buildtree(MINUSEQ, sp, p)); + + /* save the address of sp */ + sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_sue); + sp->n_lval = 0; + sp->n_rval = SP; + t->n_type = sp->n_type; + ecomp(buildtree(ASSIGN, t, sp)); +} + +/* + * Print out a string of characters. + * Assume that the assembler understands C-style escape + * sequences. + */ +void +instring(struct symtab *sp) +{ + char *s, *str; + + defloc(sp); + str = sp->sname; + + /* be kind to assemblers and avoid long strings */ + printf("\t.ascii \""); + for (s = str; *s != 0; ) { + if (*s++ == '\\') { + (void)esccon(&s); + } + if (s - str > 60) { + fwrite(str, 1, s - str, stdout); + printf("\"\n\t.ascii \""); + str = s; + } + } + fwrite(str, 1, s - str, stdout); + printf("\\0\"\n"); +} + +static int inbits = 0, inval = 0; + +/* + * set 'fsz' bits in sequence to zero. + */ +void +zbits(OFFSZ off, int fsz) +{ + int m; + + if (idebug) + printf("zbits off %lld, fsz %d inbits %d\n", off, fsz, inbits); + if ((m = (inbits % SZCHAR))) { + m = SZCHAR - m; + if (fsz < m) { + inbits += fsz; + return; + } else { + fsz -= m; + printf("\t.byte %d\n", inval); + inval = inbits = 0; + } + } + if (fsz >= SZCHAR) { + printf("\t.space %d\n", fsz/SZCHAR); + fsz -= (fsz/SZCHAR) * SZCHAR; + } + if (fsz) { + inval = 0; + inbits = fsz; + } +} + +/* + * Initialize a bitfield. + */ +void +infld(CONSZ off, int fsz, CONSZ val) +{ + if (idebug) + printf("infld off %lld, fsz %d, val %lld inbits %d\n", + off, fsz, val, inbits); + val &= (1 << fsz)-1; + while (fsz + inbits >= SZCHAR) { + inval |= (val << inbits); + printf("\t.byte %d\n", inval & 255); + fsz -= (SZCHAR - inbits); + val >>= (SZCHAR - inbits); + inval = inbits = 0; + } + if (fsz) { + inval |= (val << inbits); + inbits += fsz; + } +} + +/* + * Print an integer constant node, may be associated with a label. + * Do not free the node after use. + * 'off' is bit offset from the beginning of the aggregate + * 'fsz' is the number of bits this is referring to + */ +void +ninval(CONSZ off, int fsz, NODE *p) +{ + union { float f; double d; int i[2]; } u; + struct symtab *q; + TWORD t; + int i, j; + + t = p->n_type; + if (t > BTMASK) + t = INT; /* pointer */ + + /* + * The target-independent code does rewrite the NAME nodes + * to ICONS after we prefixed the NAME nodes with ADDROF. + * We do it here. Maybe this is too much of a hack! + */ + if (p->n_op == ADDROF && p->n_left->n_op == NAME) { + p = p->n_left; + p->n_op = ICON; + } + + if (p->n_op != ICON && p->n_op != FCON) + cerror("ninval: init node not constant: node %p", p); + + if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT) + uerror("element not constant"); + + switch (t) { + case LONGLONG: + case ULONGLONG: + i = (p->n_lval >> 32); + j = (p->n_lval & 0xffffffff); + p->n_type = INT; + if (features(FEATURE_BIGENDIAN)) { + p->n_lval = i; + ninval(off+32, 32, p); + p->n_lval = j; + ninval(off, 32, p); + } else { + p->n_lval = j; + ninval(off, 32, p); + p->n_lval = i; + ninval(off+32, 32, p); + } + break; + case INT: + case UNSIGNED: + printf("\t.word 0x%x", (int)p->n_lval); + if ((q = p->n_sp) != NULL) { + if ((q->sclass == STATIC && q->slevel > 0)) { + printf("+" LABFMT, q->soffset); + } else + printf("+%s", + q->soname ? q->soname : exname(q->sname)); + } + printf("\n"); + break; + case SHORT: + case USHORT: + printf("\t.short 0x%x\n", (int)p->n_lval & 0xffff); + break; + case BOOL: + if (p->n_lval > 1) + p->n_lval = p->n_lval != 0; + /* FALLTHROUGH */ + case CHAR: + case UCHAR: + printf("\t.byte %d\n", (int)p->n_lval & 0xff); + break; + case LDOUBLE: + case DOUBLE: + u.d = (double)p->n_dcon; +#if defined(HOST_BIG_ENDIAN) + if (features(FEATURE_BIGENDIAN)) +#else + if (!features(FEATURE_BIGENDIAN)) +#endif + printf("\t.word\t0x%x\n\t.word\t0x%x\n", + u.i[0], u.i[1]); + else + printf("\t.word\t0x%x\n\t.word\t0x%x\n", + u.i[1], u.i[0]); + break; + case FLOAT: + u.f = (float)p->n_dcon; + printf("\t.word\t0x%x\n", u.i[0]); + break; + default: + cerror("ninval"); + } +} + +/* + * Prefix a leading underscore to a global variable (if necessary). + */ +char * +exname(char *p) +{ + return (p == NULL ? "" : p); +} + +/* + * Map types which are not defined on the local machine. + */ +TWORD +ctype(TWORD type) +{ + switch (BTYPE(type)) { + case LONG: + MODTYPE(type,INT); + break; + case ULONG: + MODTYPE(type,UNSIGNED); + break; + } + return (type); +} + +/* + * Before calling a function do any tree re-writing for the local machine. + * + * 'p' is the function tree (NAME) + * 'q' is the CM-separated list of arguments. + */ +void +calldec(NODE *p, NODE *q) +{ +} + +/* + * While handling uninitialised variables, handle variables marked extern. + */ +void +extdec(struct symtab *q) +{ +} + +/* make a common declaration for id, if reasonable */ +void +defzero(struct symtab *sp) +{ + int off; + + off = tsize(sp->stype, sp->sdf, sp->ssue); + off = (off+(SZCHAR-1))/SZCHAR; + printf(" .%scomm ", sp->sclass == STATIC ? "l" : ""); + if (sp->slevel == 0) + printf("%s,0%o\n", + sp->soname ? sp->soname : exname(sp->sname), off); + else + printf(LABFMT ",0%o\n", sp->soffset, off); +} + +/* + * va_start(ap, last) implementation. + * + * f is the NAME node for this builtin function. + * a is the argument list containing: + * CM + * ap last + */ +NODE * +arm_builtin_stdarg_start(NODE *f, NODE *a) +{ + NODE *p, *q; + int sz = 1; + + /* check num args and type */ + if (a == NULL || a->n_op != CM || a->n_left->n_op == CM || + !ISPTR(a->n_left->n_type)) + goto bad; + + /* must first deal with argument size; use int size */ + p = a->n_right; + if (p->n_type < INT) { + /* round up to word */ + sz = SZINT / tsize(p->n_type, p->n_df, p->n_sue); + } + + p = buildtree(ADDROF, p, NIL); /* address of last arg */ + p = optim(buildtree(PLUS, p, bcon(sz))); + q = block(NAME, NIL, NIL, PTR+VOID, 0, 0); + q = buildtree(CAST, q, p); + p = q->n_right; + nfree(q->n_left); + nfree(q); + p = buildtree(ASSIGN, a->n_left, p); + tfree(f); + nfree(a); + + return p; + +bad: + uerror("bad argument to __builtin_stdarg_start"); + return bcon(0); +} + +NODE * +arm_builtin_va_arg(NODE *f, NODE *a) +{ + NODE *p, *q, *r; + int sz, tmpnr; + + /* check num args and type */ + if (a == NULL || a->n_op != CM || a->n_left->n_op == CM || + !ISPTR(a->n_left->n_type) || a->n_right->n_op != TYPE) + goto bad; + + r = a->n_right; + + /* get type size */ + sz = tsize(r->n_type, r->n_df, r->n_sue) / SZCHAR; + if (sz < SZINT/SZCHAR) { + werror("%s%s promoted to int when passed through ...", + ISUNSIGNED(r->n_type) ? "unsigned " : "", + DEUNSIGN(r->n_type) == SHORT ? "short" : "char"); + sz = SZINT/SZCHAR; + } + + /* alignment */ + p = tcopy(a->n_left); + if (sz > SZINT/SZCHAR && r->n_type != UNIONTY && r->n_type != STRTY) { + p = buildtree(PLUS, p, bcon(ALSTACK/8 - 1)); + p = block(AND, p, bcon(-ALSTACK/8), p->n_type, p->n_df, p->n_sue); + } + + /* create a copy to a temp node */ + q = tempnode(0, p->n_type, p->n_df, p->n_sue); + tmpnr = regno(q); + p = buildtree(ASSIGN, q, p); + + q = tempnode(tmpnr, p->n_type, p->n_df,p->n_sue); + q = buildtree(PLUS, q, bcon(sz)); + q = buildtree(ASSIGN, a->n_left, q); + + q = buildtree(COMOP, p, q); + + nfree(a->n_right); + nfree(a); + nfree(f); + + p = tempnode(tmpnr, INCREF(r->n_type), r->n_df, r->n_sue); + p = buildtree(UMUL, p, NIL); + p = buildtree(COMOP, q, p); + + return p; + +bad: + uerror("bad argument to __builtin_va_arg"); + return bcon(0); +} + +NODE * +arm_builtin_va_end(NODE *f, NODE *a) +{ + tfree(f); + tfree(a); + + return bcon(0); +} + +NODE * +arm_builtin_va_copy(NODE *f, NODE *a) +{ + if (a == NULL || a->n_op != CM || a->n_left->n_op == CM) + goto bad; + tfree(f); + f = buildtree(ASSIGN, a->n_left, a->n_right); + nfree(a); + return f; + +bad: + uerror("bad argument to __buildtin_va_copy"); + return bcon(0); +} + +char *nextsect; +static int constructor; +static int destructor; + +/* + * Give target the opportunity of handling pragmas. + */ +int +mypragma(char *str) +{ + char *a2 = pragtok(NULL); + + if (strcmp(str, "tls") == 0) { + uerror("thread-local storage not supported for this target"); + return 1; + } + if (strcmp(str, "constructor") == 0 || strcmp(str, "init") == 0) { + constructor = 1; + return 1; + } + if (strcmp(str, "destructor") == 0 || strcmp(str, "fini") == 0) { + destructor = 1; + return 1; + } + if (strcmp(str, "section") || s2 == NULL) + return 0; + nextsect = newstring(s2, strlen(s2)); + return 1; +} + +/* + * Called when a identifier has been declared, to give target last word. + */ +void +fixdef(struct symtab *sp) +{ + if ((constructor || destructor) && (sp->sclass != PARAM)) { + printf("\t.section .%ctors,\"aw\",@progbits\n", + constructor ? 'c' : 'd'); + printf("\t.p2align 2\n"); + printf("\t.long %s\n", exname(sp->sname)); + printf("\t.previous\n"); + constructor = destructor = 0; + } +} + +void +pass1_lastchance(struct interpass *ip) +{ +} diff --git a/compilers/pcc/pcc-1.0.0/arch/arm/local2.c b/compilers/pcc/pcc-1.0.0/arch/arm/local2.c new file mode 100644 index 00000000..4f5d8ec4 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/arm/local2.c @@ -0,0 +1,1496 @@ +/* $Id: local2.c,v 1.34 2008/12/14 21:16:58 ragge Exp $ */ +/* + * Copyright (c) 2007 Gregory McGarry (g.mcgarry@ieee.org). + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "pass2.h" + +extern void defalign(int); + +#define exname(x) x + +char *rnames[] = { + "r0", "r1", "r2", "r3","r4","r5", "r6", "r7", + "r8", "r9", "r10", "fp", "ip", "sp", "lr", "pc", + "r0r1", "r1r2", "r2r3", "r3r4", "r4r5", "r5r6", + "r6r7", "r7r8", "r8r9", "r9r10", + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", +}; + +/* + * Handling of integer constants. We have 8 bits + an even + * number of rotates available as a simple immediate. + * If a constant isn't trivially representable, use an ldr + * and a subsequent sequence of orr operations. + */ + +static int +trepresent(const unsigned int val) +{ + int i; +#define rotate_left(v, n) (v << n | v >> (32 - n)) + + for (i = 0; i < 32; i += 2) + if (rotate_left(val, i) <= 0xff) + return 1; + return 0; +} + +/* + * Return values are: + * 0 - output constant as is (should be covered by trepresent() above) + * 1 - 4 generate 1-4 instructions as needed. + */ +static int +encode_constant(int constant, int *values) +{ + int tmp = constant; + int i = 0; + int first_bit, value; + + while (tmp) { + first_bit = ffs(tmp); + first_bit -= 1; /* ffs indexes from 1, not 0 */ + first_bit &= ~1; /* must use even bit offsets */ + + value = tmp & (0xff << first_bit); + values[i++] = value; + tmp &= ~value; + } + return i; +} + +#if 0 +static void +load_constant(NODE *p) +{ + int v = p->n_lval & 0xffffffff; + int reg = DECRA(p->n_reg, 1); + + load_constant_into_reg(reg, v); +} +#endif + +static void +load_constant_into_reg(int reg, int v) +{ + if (trepresent(v)) + printf("\tmov %s,#%d\n", rnames[reg], v); + else if (trepresent(-v)) + printf("\tmvn %s,#%d\n", rnames[reg], -v); + else { + int vals[4], nc, i; + + nc = encode_constant(v, vals); + for (i = 0; i < nc; i++) { + if (i == 0) { + printf("\tmov %s,#%d" COM "load constant %d\n", + rnames[reg], vals[i], v); + } else { + printf("\torr %s,%s,#%d\n", + rnames[reg], rnames[reg], vals[i]); + } + } + } +} + +static TWORD ftype; + +/* + * calculate stack size and offsets + */ +static int +offcalc(struct interpass_prolog *ipp) +{ + int addto; + +#ifdef PCC_DEBUG + if (x2debug) + printf("offcalc: p2maxautooff=%d\n", p2maxautooff); +#endif + + addto = p2maxautooff; + +#if 0 + addto += 7; + addto &= ~7; +#endif + +#ifdef PCC_DEBUG + if (x2debug) + printf("offcalc: addto=%d\n", addto); +#endif + + addto -= AUTOINIT / SZCHAR; + + return addto; +} + +void +prologue(struct interpass_prolog *ipp) +{ + int addto; + int vals[4], nc, i; + +#ifdef PCC_DEBUG + if (x2debug) + printf("prologue: type=%d, lineno=%d, name=%s, vis=%d, ipptype=%d, regs=0x%x, autos=%d, tmpnum=%d, lblnum=%d\n", + ipp->ipp_ip.type, + ipp->ipp_ip.lineno, + ipp->ipp_name, + ipp->ipp_vis, + ipp->ipp_type, + ipp->ipp_regs[0], + ipp->ipp_autos, + ipp->ip_tmpnum, + ipp->ip_lblnum); +#endif + + ftype = ipp->ipp_type; + +#if 0 + printf("\t.align 2\n"); + if (ipp->ipp_vis) + printf("\t.global %s\n", exname(ipp->ipp_name)); + printf("\t.type %s,%%function\n", exname(ipp->ipp_name)); +#endif + printf("%s:\n", exname(ipp->ipp_name)); + + /* + * We here know what register to save and how much to + * add to the stack. + */ + addto = offcalc(ipp); + + printf("\tsub %s,%s,#%d\n", rnames[SP], rnames[SP], 16); + printf("\tmov %s,%s\n", rnames[IP], rnames[SP]); + printf("\tstmfd %s!,{%s,%s,%s,%s}\n", rnames[SP], rnames[FP], + rnames[IP], rnames[LR], rnames[PC]); + printf("\tsub %s,%s,#4\n", rnames[FP], rnames[IP]); + + if (addto == 0) + return; + + if (trepresent(addto)) { + printf("\tsub %s,%s,#%d\n", rnames[SP], rnames[SP], addto); + } else { + nc = encode_constant(addto, vals); + for (i = 0; i < nc; i++) + printf("\tsub %s,%s,#%d\n", + rnames[SP], rnames[SP], vals[i]); + } +} + +void +eoftn(struct interpass_prolog *ipp) +{ + if (ipp->ipp_ip.ip_lbl == 0) + return; /* no code needs to be generated */ + + /* struct return needs special treatment */ + if (ftype == STRTY || ftype == UNIONTY) { + assert(0); + } else { + printf("\tldmea %s,{%s,%s,%s}\n", rnames[FP], rnames[FP], + rnames[SP], rnames[PC]); + printf("\tadd %s,%s,#%d\n", rnames[SP], rnames[SP], 16); + } + printf("\t.size %s,.-%s\n", exname(ipp->ipp_name), + exname(ipp->ipp_name)); +} + + +/* + * these mnemonics match the order of the preprocessor decls + * EQ, NE, LE, LT, GE, GT, ULE, ULT, UGE, UGT + */ + +static char * +ccbranches[] = { + "beq", /* branch if equal */ + "bne", /* branch if not-equal */ + "ble", /* branch if less-than-or-equal */ + "blt", /* branch if less-than */ + "bge", /* branch if greater-than-or-equal */ + "bgt", /* branch if greater-than */ + /* what should these be ? */ + "bls", /* branch if lower-than-or-same */ + "blo", /* branch if lower-than */ + "bhs", /* branch if higher-than-or-same */ + "bhi", /* branch if higher-than */ +}; + +/* + * add/sub/... + * + * Param given: + */ +void +hopcode(int f, int o) +{ + char *str; + + switch (o) { + case PLUS: + str = "add"; + break; + case MINUS: + str = "sub"; + break; + case AND: + str = "and"; + break; + case OR: + str = "orr"; + break; + case ER: + str = "eor"; + break; + default: + comperr("hopcode2: %d", o); + str = 0; /* XXX gcc */ + } + printf("%s%c", str, f); +} + +/* + * Return type size in bytes. Used by R2REGS, arg 2 to offset(). + */ +int +tlen(NODE *p) +{ + switch(p->n_type) { + case CHAR: + case UCHAR: + return(1); + + case SHORT: + case USHORT: + return(SZSHORT/SZCHAR); + + case DOUBLE: + return(SZDOUBLE/SZCHAR); + + case INT: + case UNSIGNED: + case LONG: + case ULONG: + return(SZINT/SZCHAR); + + case LONGLONG: + case ULONGLONG: + return SZLONGLONG/SZCHAR; + + default: + if (!ISPTR(p->n_type)) + comperr("tlen type %d not pointer"); + return SZPOINT(p->n_type)/SZCHAR; + } +} + +/* + * Emit code to compare two longlong numbers. + */ +static void +twollcomp(NODE *p) +{ + int o = p->n_op; + int s = getlab2(); + int e = p->n_label; + int cb1, cb2; + + if (o >= ULE) + o -= (ULE-LE); + switch (o) { + case NE: + cb1 = 0; + cb2 = NE; + break; + case EQ: + cb1 = NE; + cb2 = 0; + break; + case LE: + case LT: + cb1 = GT; + cb2 = LT; + break; + case GE: + case GT: + cb1 = LT; + cb2 = GT; + break; + + default: + cb1 = cb2 = 0; /* XXX gcc */ + } + if (p->n_op >= ULE) + cb1 += 4, cb2 += 4; + expand(p, 0, "\tcmp UR,UL" COM "compare 64-bit values (upper)\n"); + if (cb1) cbgen(cb1, s); + if (cb2) cbgen(cb2, e); + expand(p, 0, "\tcmp AR,AL" COM "(and lower)\n"); + cbgen(p->n_op, e); + deflab(s); +} + +int +fldexpand(NODE *p, int cookie, char **cp) +{ + CONSZ val; + int shft; + + if (p->n_op == ASSIGN) + p = p->n_left; + + if (features(FEATURE_BIGENDIAN)) + shft = SZINT - UPKFSZ(p->n_rval) - UPKFOFF(p->n_rval); + else + shft = UPKFOFF(p->n_rval); + + switch (**cp) { + case 'S': + printf("#%d", UPKFSZ(p->n_rval)); + break; + case 'H': + printf("#%d", shft); + break; + case 'M': + case 'N': + val = (CONSZ)1 << UPKFSZ(p->n_rval); + --val; + val <<= shft; + printf("%lld", (**cp == 'M' ? val : ~val) & 0xffffffff); + break; + default: + comperr("fldexpand"); + } + return 1; +} + + +/* + * Structure assignment. + */ +static void +stasg(NODE *p) +{ + NODE *l = p->n_left; + int val = l->n_lval; + + /* R0 = dest, R1 = src, R2 = len */ + load_constant_into_reg(R2, p->n_stsize); + if (l->n_op == OREG) { + if (R2TEST(regno(l))) { + int r = regno(l); + printf("\tadd %s,%s,lsl #%d\n", + rnames[R0], rnames[R2UPK2(r)], R2UPK3(r)); + printf("\tadd %s,%s,%s\n", rnames[R0], rnames[R0], + rnames[R2UPK1(r)]); + } else { + if (trepresent(val)) { + printf("\tadd %s,%s,#%d\n", + rnames[R0], rnames[regno(l)], val); + } else { + load_constant_into_reg(R0, val); + printf("\tadd %s,%s,%s\n", rnames[R0], + rnames[R0], rnames[regno(l)]); + } + } + } else if (l->n_op == NAME) { + cerror("not implemented"); + } + + printf("\tbl %s\n", exname("memcpy")); +} + +static void +shiftop(NODE *p) +{ + NODE *r = p->n_right; + TWORD ty = p->n_type; + char *shifttype; + + if (p->n_op == LS && r->n_op == ICON && r->n_lval < 32) { + expand(p, INBREG, "\tmov A1,AL,lsr "); + printf(CONFMT COM "64-bit left-shift\n", 32 - r->n_lval); + expand(p, INBREG, "\tmov U1,UL,asl AR\n"); + expand(p, INBREG, "\torr U1,U1,A1\n"); + expand(p, INBREG, "\tmov A1,AL,asl AR\n"); + } else if (p->n_op == LS && r->n_op == ICON && r->n_lval < 64) { + expand(p, INBREG, "\tmov A1,#0" COM "64-bit left-shift\n"); + expand(p, INBREG, "\tmov U1,AL"); + if (r->n_lval - 32 != 0) + printf(",asl " CONFMT, r->n_lval - 32); + printf("\n"); + } else if (p->n_op == LS && r->n_op == ICON) { + expand(p, INBREG, "\tmov A1,#0" COM "64-bit left-shift\n"); + expand(p, INBREG, "\tmov U1,#0\n"); + } else if (p->n_op == RS && r->n_op == ICON && r->n_lval < 32) { + expand(p, INBREG, "\tmov U1,UL,asl "); + printf(CONFMT COM "64-bit right-shift\n", 32 - r->n_lval); + expand(p, INBREG, "\tmov A1,AL,lsr AR\n"); + expand(p, INBREG, "\torr A1,A1,U1\n"); + if (ty == LONGLONG) + expand(p, INBREG, "\tmov U1,UL,asr AR\n"); + else + expand(p, INBREG, "\tmov U1,UL,lsr AR\n"); + } else if (p->n_op == RS && r->n_op == ICON && r->n_lval < 64) { + if (ty == LONGLONG) { + expand(p, INBREG, "\tmvn U1,#1" COM "64-bit right-shift\n"); + expand(p, INBREG, "\tmov A1,UL"); + shifttype = "asr"; + }else { + expand(p, INBREG, "\tmov U1,#0" COM "64-bit right-shift\n"); + expand(p, INBREG, "\tmov A1,UL"); + shifttype = "lsr"; + } + if (r->n_lval - 32 != 0) + printf(",%s " CONFMT, shifttype, r->n_lval - 32); + printf("\n"); + } else if (p->n_op == RS && r->n_op == ICON) { + expand(p, INBREG, "\tmov A1,#0" COM "64-bit right-shift\n"); + expand(p, INBREG, "\tmov U1,#0\n"); + } +} + +/* + * http://gcc.gnu.org/onlinedocs/gccint/Soft-float-library-routines.html#Soft-float-library-routines + */ +static void +fpemul(NODE *p) +{ + NODE *l = p->n_left; + char *ch = NULL; + + if (p->n_op == PLUS && p->n_type == FLOAT) ch = "addsf3"; + else if (p->n_op == PLUS && p->n_type == DOUBLE) ch = "adddf3"; + else if (p->n_op == PLUS && p->n_type == LDOUBLE) ch = "adddf3"; + + else if (p->n_op == MINUS && p->n_type == FLOAT) ch = "subsf3"; + else if (p->n_op == MINUS && p->n_type == DOUBLE) ch = "subdf3"; + else if (p->n_op == MINUS && p->n_type == LDOUBLE) ch = "subdf3"; + + else if (p->n_op == MUL && p->n_type == FLOAT) ch = "mulsf3"; + else if (p->n_op == MUL && p->n_type == DOUBLE) ch = "muldf3"; + else if (p->n_op == MUL && p->n_type == LDOUBLE) ch = "muldf3"; + + else if (p->n_op == DIV && p->n_type == FLOAT) ch = "divsf3"; + else if (p->n_op == DIV && p->n_type == DOUBLE) ch = "divdf3"; + else if (p->n_op == DIV && p->n_type == LDOUBLE) ch = "divdf3"; + + else if (p->n_op == UMINUS && p->n_type == FLOAT) ch = "negsf2"; + else if (p->n_op == UMINUS && p->n_type == DOUBLE) ch = "negdf2"; + else if (p->n_op == UMINUS && p->n_type == LDOUBLE) ch = "negdf2"; + + else if (p->n_op == EQ && l->n_type == FLOAT) ch = "eqsf2"; + else if (p->n_op == EQ && l->n_type == DOUBLE) ch = "eqdf2"; + else if (p->n_op == EQ && l->n_type == LDOUBLE) ch = "eqdf2"; + + else if (p->n_op == NE && l->n_type == FLOAT) ch = "nesf2"; + else if (p->n_op == NE && l->n_type == DOUBLE) ch = "nedf2"; + else if (p->n_op == NE && l->n_type == LDOUBLE) ch = "nedf2"; + + else if (p->n_op == GE && l->n_type == FLOAT) ch = "gesf2"; + else if (p->n_op == GE && l->n_type == DOUBLE) ch = "gedf2"; + else if (p->n_op == GE && l->n_type == LDOUBLE) ch = "gedf2"; + + else if (p->n_op == LE && l->n_type == FLOAT) ch = "lesf2"; + else if (p->n_op == LE && l->n_type == DOUBLE) ch = "ledf2"; + else if (p->n_op == LE && l->n_type == LDOUBLE) ch = "ledf2"; + + else if (p->n_op == GT && l->n_type == FLOAT) ch = "gtsf2"; + else if (p->n_op == GT && l->n_type == DOUBLE) ch = "gtdf2"; + else if (p->n_op == GT && l->n_type == LDOUBLE) ch = "gtdf2"; + + else if (p->n_op == LT && l->n_type == FLOAT) ch = "ltsf2"; + else if (p->n_op == LT && l->n_type == DOUBLE) ch = "ltdf2"; + else if (p->n_op == LT && l->n_type == LDOUBLE) ch = "ltdf2"; + + else if (p->n_op == SCONV && p->n_type == FLOAT) { + if (l->n_type == DOUBLE) ch = "truncdfsf2"; + else if (l->n_type == LDOUBLE) ch = "truncdfsf2"; + else if (l->n_type == ULONGLONG) ch = "floatunsdisf"; + else if (l->n_type == LONGLONG) ch = "floatdisf"; + else if (l->n_type == LONG) ch = "floatsisf"; + else if (l->n_type == ULONG) ch = "floatunsisf"; + else if (l->n_type == INT) ch = "floatsisf"; + else if (l->n_type == UNSIGNED) ch = "floatunsisf"; + } else if (p->n_op == SCONV && p->n_type == DOUBLE) { + if (l->n_type == FLOAT) ch = "extendsfdf2"; + else if (l->n_type == LDOUBLE) ch = "trunctfdf2"; + else if (l->n_type == ULONGLONG) ch = "floatunsdidf"; + else if (l->n_type == LONGLONG) ch = "floatdidf"; + else if (l->n_type == LONG) ch = "floatsidf"; + else if (l->n_type == ULONG) ch = "floatunsidf"; + else if (l->n_type == INT) ch = "floatsidf"; + else if (l->n_type == UNSIGNED) ch = "floatunsidf"; + } else if (p->n_op == SCONV && p->n_type == LDOUBLE) { + if (l->n_type == FLOAT) ch = "extendsfdf2"; + else if (l->n_type == DOUBLE) ch = "extenddftd2"; + else if (l->n_type == ULONGLONG) ch = "floatunsdidf"; + else if (l->n_type == LONGLONG) ch = "floatdidf"; + else if (l->n_type == LONG) ch = "floatsidf"; + else if (l->n_type == ULONG) ch = "floatunsidf"; + else if (l->n_type == INT) ch = "floatsidf"; + else if (l->n_type == UNSIGNED) ch = "floatunsidf"; + } else if (p->n_op == SCONV && p->n_type == ULONGLONG) { + if (l->n_type == FLOAT) ch = "fixunssfdi"; + else if (l->n_type == DOUBLE) ch = "fixunsdfdi"; + else if (l->n_type == LDOUBLE) ch = "fixunsdfdi"; + } else if (p->n_op == SCONV && p->n_type == LONGLONG) { + if (l->n_type == FLOAT) ch = "fixsfdi"; + else if (l->n_type == DOUBLE) ch = "fixdfdi"; + else if (l->n_type == LDOUBLE) ch = "fixdfdi"; + } else if (p->n_op == SCONV && p->n_type == LONG) { + if (l->n_type == FLOAT) ch = "fixsfsi"; + else if (l->n_type == DOUBLE) ch = "fixdfsi"; + else if (l->n_type == LDOUBLE) ch = "fixdfsi"; + } else if (p->n_op == SCONV && p->n_type == ULONG) { + if (l->n_type == FLOAT) ch = "fixunssfdi"; + else if (l->n_type == DOUBLE) ch = "fixunsdfdi"; + else if (l->n_type == LDOUBLE) ch = "fixunsdfdi"; + } else if (p->n_op == SCONV && p->n_type == INT) { + if (l->n_type == FLOAT) ch = "fixsfsi"; + else if (l->n_type == DOUBLE) ch = "fixdfsi"; + else if (l->n_type == LDOUBLE) ch = "fixdfsi"; + } else if (p->n_op == SCONV && p->n_type == UNSIGNED) { + if (l->n_type == FLOAT) ch = "fixunssfsi"; + else if (l->n_type == DOUBLE) ch = "fixunsdfsi"; + else if (l->n_type == LDOUBLE) ch = "fixunsdfsi"; + } + + if (ch == NULL) comperr("ZF: op=0x%x (%d)\n", p->n_op, p->n_op); + + printf("\tbl __%s" COM "softfloat operation\n", exname(ch)); + + if (p->n_op >= EQ && p->n_op <= GT) + printf("\tcmp %s,#0\n", rnames[R0]); +} + + +/* + * http://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html#Integer-library-routines + */ + +static void +emul(NODE *p) +{ + char *ch = NULL; + + if (p->n_op == LS && DEUNSIGN(p->n_type) == LONGLONG) ch = "ashldi3"; + else if (p->n_op == LS && DEUNSIGN(p->n_type) == LONG) ch = "ashlsi3"; + else if (p->n_op == LS && DEUNSIGN(p->n_type) == INT) ch = "ashlsi3"; + + else if (p->n_op == RS && p->n_type == ULONGLONG) ch = "lshrdi3"; + else if (p->n_op == RS && p->n_type == ULONG) ch = "lshrsi3"; + else if (p->n_op == RS && p->n_type == UNSIGNED) ch = "lshrsi3"; + + else if (p->n_op == RS && p->n_type == LONGLONG) ch = "ashrdi3"; + else if (p->n_op == RS && p->n_type == LONG) ch = "ashrsi3"; + else if (p->n_op == RS && p->n_type == INT) ch = "ashrsi3"; + + else if (p->n_op == DIV && p->n_type == LONGLONG) ch = "divdi3"; + else if (p->n_op == DIV && p->n_type == LONG) ch = "divsi3"; + else if (p->n_op == DIV && p->n_type == INT) ch = "divsi3"; + + else if (p->n_op == DIV && p->n_type == ULONGLONG) ch = "udivdi3"; + else if (p->n_op == DIV && p->n_type == ULONG) ch = "udivsi3"; + else if (p->n_op == DIV && p->n_type == UNSIGNED) ch = "udivsi3"; + + else if (p->n_op == MOD && p->n_type == LONGLONG) ch = "moddi3"; + else if (p->n_op == MOD && p->n_type == LONG) ch = "modsi3"; + else if (p->n_op == MOD && p->n_type == INT) ch = "modsi3"; + + else if (p->n_op == MOD && p->n_type == ULONGLONG) ch = "umoddi3"; + else if (p->n_op == MOD && p->n_type == ULONG) ch = "umodsi3"; + else if (p->n_op == MOD && p->n_type == UNSIGNED) ch = "umodsi3"; + + else if (p->n_op == MUL && p->n_type == LONGLONG) ch = "muldi3"; + else if (p->n_op == MUL && p->n_type == LONG) ch = "mulsi3"; + else if (p->n_op == MUL && p->n_type == INT) ch = "mulsi3"; + + else if (p->n_op == UMINUS && p->n_type == LONGLONG) ch = "negdi2"; + else if (p->n_op == UMINUS && p->n_type == LONG) ch = "negsi2"; + else if (p->n_op == UMINUS && p->n_type == INT) ch = "negsi2"; + + else ch = 0, comperr("ZE"); + printf("\tbl __%s" COM "emulated operation\n", exname(ch)); +} + +static void +halfword(NODE *p) +{ + NODE *r = getlr(p, 'R'); + NODE *l = getlr(p, 'L'); + int idx0 = 0, idx1 = 1; + + if (features(FEATURE_BIGENDIAN)) { + idx0 = 1; + idx1 = 0; + } + + if (p->n_op == ASSIGN && r->n_op == OREG) { + /* load */ + expand(p, 0, "\tldrb A1,"); + printf("[%s," CONFMT "]\n", rnames[r->n_rval], r->n_lval+idx0); + expand(p, 0, "\tldrb AL,"); + printf("[%s," CONFMT "]\n", rnames[r->n_rval], r->n_lval+idx1); + expand(p, 0, "\torr AL,A1,AL,asl #8\n"); + } else if (p->n_op == ASSIGN && l->n_op == OREG) { + /* store */ + expand(p, 0, "\tstrb AR,"); + printf("[%s," CONFMT "]\n", rnames[l->n_rval], l->n_lval+idx0); + expand(p, 0, "\tmov A1,AR,asr #8\n"); + expand(p, 0, "\tstrb A1,"); + printf("[%s," CONFMT "]\n", rnames[l->n_rval], l->n_lval+idx1); + } else if (p->n_op == SCONV || p->n_op == UMUL) { + /* load */ + expand(p, 0, "\tldrb A1,"); + printf("[%s," CONFMT "]\n", rnames[l->n_rval], l->n_lval+idx0); + expand(p, 0, "\tldrb A2,"); + printf("[%s," CONFMT "]\n", rnames[l->n_rval], l->n_lval+idx1); + expand(p, 0, "\torr A1,A1,A2,asl #8\n"); + } else if (p->n_op == NAME || p->n_op == ICON || p->n_op == OREG) { + /* load */ + expand(p, 0, "\tldrb A1,"); + printf("[%s," CONFMT "]\n", rnames[p->n_rval], p->n_lval+idx0); + expand(p, 0, "\tldrb A2,"); + printf("[%s," CONFMT "]\n", rnames[p->n_rval], p->n_lval+idx1); + expand(p, 0, "\torr A1,A1,A2,asl #8\n"); + } else { + comperr("halfword"); + } +} + +static void +bfext(NODE *p) +{ + int sz; + + if (ISUNSIGNED(p->n_right->n_type)) + return; + sz = 32 - UPKFSZ(p->n_left->n_rval); + + expand(p, 0, "\tmov AD,AD,asl "); + printf("#%d\n", sz); + expand(p, 0, "\tmov AD,AD,asr "); + printf("#%d\n", sz); +} + +static int +argsiz(NODE *p) +{ + TWORD t = p->n_type; + + if (t < LONGLONG || t == FLOAT || t > BTMASK) + return 4; + if (t == LONGLONG || t == ULONGLONG) + return 8; + if (t == DOUBLE || t == LDOUBLE) + return 8; + if (t == STRTY || t == UNIONTY) + return p->n_stsize; + comperr("argsiz"); + return 0; +} + +void +zzzcode(NODE *p, int c) +{ + int pr; + + switch (c) { + + case 'B': /* bit-field sign extension */ + bfext(p); + break; + + case 'C': /* remove from stack after subroutine call */ + pr = p->n_qual; +#if 0 + if (p->n_op == STCALL || p->n_op == USTCALL) + pr += 4; +#endif + if (p->n_op == UCALL) + return; /* XXX remove ZC from UCALL */ + if (pr > 0) + printf("\tadd %s,%s,#%d\n", rnames[SP], rnames[SP], pr); + break; + + case 'D': /* Long long comparision */ + twollcomp(p); + break; + + case 'E': /* print out emulated ops */ + emul(p); + break; + + case 'F': /* print out emulated floating-point ops */ + fpemul(p); + break; + + case 'H': /* do halfword access */ + halfword(p); + break; + + case 'I': /* init constant */ + if (p->n_name[0] != '\0') + comperr("named init"); + load_constant_into_reg(DECRA(p->n_reg, 1), + p->n_lval & 0xffffffff); + break; + + case 'J': /* init longlong constant */ + load_constant_into_reg(DECRA(p->n_reg, 1) - R0R1, + p->n_lval & 0xffffffff); + load_constant_into_reg(DECRA(p->n_reg, 1) - R0R1 + 1, + (p->n_lval >> 32)); + break; + + case 'O': /* 64-bit left and right shift operators */ + shiftop(p); + break; + + case 'Q': /* emit struct assign */ + stasg(p); + break; + + default: + comperr("zzzcode %c", c); + } +} + +/*ARGSUSED*/ +int +rewfld(NODE *p) +{ + return(1); +} + +/* + * Does the bitfield shape match? + */ +int +flshape(NODE *p) +{ + int o = p->n_op; + + if (o == OREG || o == REG || o == NAME) + return SRDIR; /* Direct match */ + if (o == UMUL && shumul(p->n_left, SOREG)) + return SROREG; /* Convert into oreg */ + return SRREG; /* put it into a register */ +} + +/* INTEMP shapes must not contain any temporary registers */ +/* XXX should this go away now? */ +int +shtemp(NODE *p) +{ + return 0; +#if 0 + int r; + + if (p->n_op == STARG ) + p = p->n_left; + + switch (p->n_op) { + case REG: + return (!istreg(p->n_rval)); + + case OREG: + r = p->n_rval; + if (R2TEST(r)) { + if (istreg(R2UPK1(r))) + return(0); + r = R2UPK2(r); + } + return (!istreg(r)); + + case UMUL: + p = p->n_left; + return (p->n_op != UMUL && shtemp(p)); + } + + if (optype(p->n_op) != LTYPE) + return(0); + return(1); +#endif +} + +void +adrcon(CONSZ val) +{ + printf(CONFMT, val); +} + +void +conput(FILE *fp, NODE *p) +{ + char *s; + int val = p->n_lval; + + switch (p->n_op) { + case ICON: +#if 0 + if (p->n_sp) + printf(" [class=%d,level=%d] ", p->n_sp->sclass, p->n_sp->slevel); +#endif +#ifdef notdef /* ICON cannot ever use sp here */ + /* If it does, it's a giant bug */ + if (p->n_sp == NULL || ( + (p->n_sp->sclass == STATIC && p->n_sp->slevel > 0))) + s = p->n_name; + else + s = exname(p->n_name); +#else + s = p->n_name; +#endif + + if (*s != '\0') { + fprintf(fp, "%s", s); + if (val > 0) + fprintf(fp, "+%d", val); + else if (val < 0) + fprintf(fp, "-%d", -val); + } else + fprintf(fp, CONFMT, (CONSZ)val); + return; + + default: + comperr("illegal conput, p %p", p); + } +} + +/*ARGSUSED*/ +void +insput(NODE *p) +{ + comperr("insput"); +} + +/* + * Write out the upper address, like the upper register of a 2-register + * reference, or the next memory location. + */ +void +upput(NODE *p, int size) +{ + + size /= SZCHAR; + switch (p->n_op) { + case REG: + fprintf(stdout, "%s", rnames[p->n_rval-R0R1+1]); + break; + + case NAME: + case OREG: + p->n_lval += size; + adrput(stdout, p); + p->n_lval -= size; + break; + case ICON: + fprintf(stdout, CONFMT, p->n_lval >> 32); + break; + default: + comperr("upput bad op %d size %d", p->n_op, size); + } +} + +void +adrput(FILE *io, NODE *p) +{ + int r; + /* output an address, with offsets, from p */ + + if (p->n_op == FLD) + p = p->n_left; + + switch (p->n_op) { + + case NAME: + if (p->n_name[0] != '\0') { + fputs(p->n_name, io); + if (p->n_lval != 0) + fprintf(io, "+%lld", p->n_lval); + } else + fprintf(io, CONFMT, p->n_lval); + return; + + case OREG: + r = p->n_rval; + if (R2TEST(r)) + fprintf(io, "[%s, %s, lsl #%d]", + rnames[R2UPK1(r)], + rnames[R2UPK2(r)], + R2UPK3(r)); + else + fprintf(io, "[%s,#%d]", rnames[p->n_rval], (int)p->n_lval); + return; + + case ICON: + /* addressable value of the constant */ + conput(io, p); + return; + + case REG: + switch (p->n_type) { + case DOUBLE: + case LDOUBLE: + if (features(FEATURE_HARDFLOAT)) { + fprintf(io, "%s", rnames[p->n_rval]); + break; + } + /* FALLTHROUGH */ + case LONGLONG: + case ULONGLONG: + fprintf(stdout, "%s", rnames[p->n_rval-R0R1]); + break; + default: + fprintf(io, "%s", rnames[p->n_rval]); + } + return; + + default: + comperr("illegal address, op %d, node %p", p->n_op, p); + return; + + } +} + +/* printf conditional and unconditional branches */ +void +cbgen(int o, int lab) +{ + if (o < EQ || o > UGT) + comperr("bad conditional branch: %s", opst[o]); + printf("\t%s " LABFMT COM "conditional branch\n", + ccbranches[o-EQ], lab); +} + +/* + * The arm can only address 4k to get a NAME, so there must be some + * rewriting here. Strategy: + * For first 1000 nodes found, print out the word directly. + * For the following 1000 nodes, group them together in asm statements + * and create a jump over. + * For the last <1000 statements, print out the words last. + */ +struct addrsymb { + SLIST_ENTRY(addrsymb) link; + char *name; /* symbol name */ + int num; /* symbol offset */ + char *str; /* replace label */ +}; +SLIST_HEAD(, addrsymb) aslist; +static struct interpass *ipbase; +static int prtnumber, nodcnt, notfirst; +#define PRTLAB ".LY%d" /* special for here */ + +static struct interpass * +anode(char *p) +{ + extern int thisline; + struct interpass *ip = tmpalloc(sizeof(struct interpass)); + + ip->ip_asm = p; + ip->type = IP_ASM; + ip->lineno = thisline; + return ip; +} + +static void +flshlab(void) +{ + struct interpass *ip; + struct addrsymb *el; + int lab = prtnumber++; + char *c; + + if (SLIST_FIRST(&aslist) == NULL) + return; + + snprintf(c = tmpalloc(32), 32, "\tb " PRTLAB "\n", lab); + ip = anode(c); + DLIST_INSERT_BEFORE(ipbase, ip, qelem); + + SLIST_FOREACH(el, &aslist, link) { + /* insert each node as asm */ + int l = 32+strlen(el->name); + c = tmpalloc(l); + if (el->num) + snprintf(c, l, "%s:\n\t.word %s+%d\n", + el->str, el->name, el->num); + else + snprintf(c, l, "%s:\n\t.word %s\n", el->str, el->name); + ip = anode(c); + DLIST_INSERT_BEFORE(ipbase, ip, qelem); + } + /* generate asm label */ + snprintf(c = tmpalloc(32), 32, PRTLAB ":\n", lab); + ip = anode(c); + DLIST_INSERT_BEFORE(ipbase, ip, qelem); +} + +static void +prtaddr(NODE *p, void *arg) +{ + NODE *l = p->n_left; + struct addrsymb *el; + int found = 0; + int lab; + + nodcnt++; + + if (p->n_op == ASSIGN && p->n_right->n_op == ICON && + p->n_right->n_name[0] != '\0') { + /* named constant */ + p = p->n_right; + + /* Restore addrof */ + l = mklnode(NAME, p->n_lval, 0, 0); + l->n_name = p->n_name; + p->n_left = l; + p->n_op = ADDROF; + } + + if (p->n_op != ADDROF || l->n_op != NAME) + return; + + /* if we passed 1k nodes printout list */ + if (nodcnt > 1000) { + if (notfirst) + flshlab(); + SLIST_INIT(&aslist); + notfirst = 1; + nodcnt = 0; + } + + /* write address to byte stream */ + + SLIST_FOREACH(el, &aslist, link) { + if (el->num == l->n_lval && el->name[0] == l->n_name[0] && + strcmp(el->name, l->n_name) == 0) { + found = 1; + break; + } + } + + if (!found) { + /* we know that this is text segment */ + lab = prtnumber++; + if (nodcnt <= 1000 && notfirst == 0) { + if (l->n_lval) + printf(PRTLAB ":\n\t.word %s+%lld\n", + lab, l->n_name, l->n_lval); + else + printf(PRTLAB ":\n\t.word %s\n", + lab, l->n_name); + } + el = tmpalloc(sizeof(struct addrsymb)); + el->num = l->n_lval; + el->name = l->n_name; + el->str = tmpalloc(32); + snprintf(el->str, 32, PRTLAB, lab); + SLIST_INSERT_LAST(&aslist, el, link); + } + + nfree(l); + p->n_op = NAME; + p->n_lval = 0; + p->n_name = el->str; +} + +void +myreader(struct interpass *ipole) +{ + struct interpass *ip; + + SLIST_INIT(&aslist); + notfirst = nodcnt = 0; + + DLIST_FOREACH(ip, ipole, qelem) { + switch (ip->type) { + case IP_NODE: + lineno = ip->lineno; + ipbase = ip; + walkf(ip->ip_node, prtaddr, 0); + break; + case IP_EPILOG: + ipbase = ip; + if (notfirst) + flshlab(); + break; + default: + break; + } + } + if (x2debug) + printip(ipole); +} + +/* + * Remove some PCONVs after OREGs are created. + */ +static void +pconv2(NODE *p, void *arg) +{ + NODE *q; + + if (p->n_op == PLUS) { + if (p->n_type == (PTR+SHORT) || p->n_type == (PTR+USHORT)) { + if (p->n_right->n_op != ICON) + return; + if (p->n_left->n_op != PCONV) + return; + if (p->n_left->n_left->n_op != OREG) + return; + q = p->n_left->n_left; + nfree(p->n_left); + p->n_left = q; + /* + * This will be converted to another OREG later. + */ + } + } +} + +void +mycanon(NODE *p) +{ + walkf(p, pconv2, 0); +} + +void +myoptim(struct interpass *ipp) +{ +} + +/* + * Register move: move contents of register 's' to register 'r'. + */ +void +rmove(int s, int d, TWORD t) +{ + switch (t) { + case DOUBLE: + case LDOUBLE: + if (features(FEATURE_HARDFLOAT)) { + printf("\tfmr %s,%s" COM "rmove\n", + rnames[d], rnames[s]); + break; + } + /* FALLTHROUGH */ + case LONGLONG: + case ULONGLONG: +#define LONGREG(x, y) rnames[(x)-(R0R1-(y))] + if (s == d+1) { + /* dh = sl, copy low word first */ + printf("\tmov %s,%s" COM "rmove\n", + LONGREG(d,0), LONGREG(s,0)); + printf("\tmov %s,%s\n", + LONGREG(d,1), LONGREG(s,1)); + } else { + /* copy high word first */ + printf("\tmov %s,%s" COM "rmove\n", + LONGREG(d,1), LONGREG(s,1)); + printf("\tmov %s,%s\n", + LONGREG(d,0), LONGREG(s,0)); + } +#undef LONGREG + break; + case FLOAT: + if (features(FEATURE_HARDFLOAT)) { + printf("\tmr %s,%s" COM "rmove\n", + rnames[d], rnames[s]); + break; + } + /* FALLTHROUGH */ + default: + printf("\tmov %s,%s" COM "rmove\n", rnames[d], rnames[s]); + } +} + +/* + * Can we assign a register from class 'c', given the set + * of number of assigned registers in each class 'r'. + * + * On ARM, we have: + * 11 CLASSA registers (32-bit hard registers) + * 10 CLASSB registers (64-bit composite registers) + * 8 or 32 CLASSC registers (floating-point) + * + * There is a problem calculating the available composite registers + * (ie CLASSB). The algorithm below assumes that given any two + * registers, we can make a composite register. But this isn't true + * here (or with other targets), since the number of combinations + * of register pairs could become very large. Additionally, + * having so many combinations really isn't so practical, since + * most register pairs cannot be used to pass function arguments. + * Consequently, when there is pressure composite registers, + * "beenhere" compilation failures are common. + * + * [We need to know which registers are allocated, not simply + * the number in each class] + */ +int +COLORMAP(int c, int *r) +{ + int num = 0; /* number of registers used */ + +#if 0 + static const char classes[] = { 'X', 'A', 'B', 'C', 'D' }; + printf("COLORMAP: requested class %c\n", classes[c]); + printf("COLORMAP: class A: %d\n", r[CLASSA]); + printf("COLORMAP: class B: %d\n", r[CLASSB]); +#endif + + switch (c) { + case CLASSA: + num += r[CLASSA]; + num += 2*r[CLASSB]; + return num < 11; + case CLASSB: + num += 2*r[CLASSB]; + num += r[CLASSA]; + return num < 6; /* XXX see comments above */ + case CLASSC: + num += r[CLASSC]; + if (features(FEATURE_FPA)) + return num < 8; + else if (features(FEATURE_VFP)) + return num < 8; + else + cerror("colormap 1"); + } + cerror("colormap 2"); + return 0; /* XXX gcc */ +} + +/* + * Return a class suitable for a specific type. + */ +int +gclass(TWORD t) +{ + if (t == DOUBLE || t == LDOUBLE) { + if (features(FEATURE_HARDFLOAT)) + return CLASSC; + else + return CLASSB; + } + if (t == FLOAT) { + if (features(FEATURE_HARDFLOAT)) + return CLASSC; + else + return CLASSA; + } + if (DEUNSIGN(t) == LONGLONG) + return CLASSB; + return CLASSA; +} + +int +retreg(int t) +{ + int c = gclass(t); + if (c == CLASSB) + return R0R1; + else if (c == CLASSC) + return F0; + return R0; +} + +/* + * Calculate argument sizes. + */ +void +lastcall(NODE *p) +{ + NODE *op = p; + int size = 0; + + p->n_qual = 0; + if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL) + return; + for (p = p->n_right; p->n_op == CM; p = p->n_left) + size += argsiz(p->n_right); + size += argsiz(p); + op->n_qual = size - 16; /* XXX */ +} + +/* + * Special shapes. + */ +int +special(NODE *p, int shape) +{ + return SRNOPE; +} + +/* + * default to ARMv2 + */ +#ifdef TARGET_BIG_ENDIAN +#define DEFAULT_FEATURES FEATURE_BIGENDIAN | FEATURE_MUL +#else +#define DEFAULT_FEATURES FEATURE_MUL +#endif + +static int fset = DEFAULT_FEATURES; + +/* + * Target-dependent command-line options. + */ +void +mflags(char *str) +{ + if (strcasecmp(str, "little-endian") == 0) { + fset &= ~FEATURE_BIGENDIAN; + } else if (strcasecmp(str, "big-endian") == 0) { + fset |= FEATURE_BIGENDIAN; + } else if (strcasecmp(str, "fpe=fpa") == 0) { + fset &= ~(FEATURE_VFP | FEATURE_FPA); + fset |= FEATURE_FPA; + } else if (strcasecmp(str, "fpe=vfp") == 0) { + fset &= ~(FEATURE_VFP | FEATURE_FPA); + fset |= FEATURE_VFP; + } else if (strcasecmp(str, "soft-float") == 0) { + fset &= ~(FEATURE_VFP | FEATURE_FPA); + } else if (strcasecmp(str, "arch=armv1") == 0) { + fset &= ~FEATURE_HALFWORDS; + fset &= ~FEATURE_EXTEND; + fset &= ~FEATURE_MUL; + fset &= ~FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv2") == 0) { + fset &= ~FEATURE_HALFWORDS; + fset &= ~FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset &= ~FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv2a") == 0) { + fset &= ~FEATURE_HALFWORDS; + fset &= ~FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset &= ~FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv3") == 0) { + fset &= ~FEATURE_HALFWORDS; + fset &= ~FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset &= ~FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv4") == 0) { + fset |= FEATURE_HALFWORDS; + fset &= ~FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset |= FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv4t") == 0) { + fset |= FEATURE_HALFWORDS; + fset &= ~FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset |= FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv4tej") == 0) { + fset |= FEATURE_HALFWORDS; + fset &= ~FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset |= FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv5") == 0) { + fset |= FEATURE_HALFWORDS; + fset &= ~FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset |= FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv5te") == 0) { + fset |= FEATURE_HALFWORDS; + fset &= ~FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset |= FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv5tej") == 0) { + fset |= FEATURE_HALFWORDS; + fset &= ~FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset |= FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv6") == 0) { + fset |= FEATURE_HALFWORDS; + fset |= FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset |= FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv6t2") == 0) { + fset |= FEATURE_HALFWORDS; + fset |= FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset |= FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv6kz") == 0) { + fset |= FEATURE_HALFWORDS; + fset |= FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset |= FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv6k") == 0) { + fset |= FEATURE_HALFWORDS; + fset |= FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset |= FEATURE_MULL; + } else if (strcasecmp(str, "arch=armv7") == 0) { + fset |= FEATURE_HALFWORDS; + fset |= FEATURE_EXTEND; + fset |= FEATURE_MUL; + fset |= FEATURE_MULL; + } else { + fprintf(stderr, "unknown m option '%s'\n", str); + exit(1); + } +} + +int +features(int mask) +{ + if (mask == FEATURE_HARDFLOAT) + return ((fset & mask) != 0); + return ((fset & mask) == mask); +} + +/* + * Define the current location as an internal label. + */ +void +deflab(int label) +{ + printf(LABFMT ":\n", label); +} + +/* + * Do something target-dependent for xasm arguments. + * Supposed to find target-specific constraints and rewrite them. + */ +int +myxasm(struct interpass *ip, NODE *p) +{ + return 0; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/arm/macdefs.h b/compilers/pcc/pcc-1.0.0/arch/arm/macdefs.h new file mode 100644 index 00000000..6e0c2ed9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/arm/macdefs.h @@ -0,0 +1,263 @@ +/* $Id: macdefs.h,v 1.12 2009/01/24 21:43:48 gmcgarry Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Machine-dependent defines for both passes. + */ + +/* + * Convert (multi-)character constant to integer. + */ +#define makecc(val,i) lastcon = (lastcon<<8)|((val<<24)>>24); + +/* + * Storage space requirements + */ +#define SZCHAR 8 +#define SZBOOL 32 +#define SZINT 32 +#define SZFLOAT 32 +#define SZDOUBLE 64 +#define SZLDOUBLE 64 +#define SZLONG 32 +#define SZSHORT 16 +#define SZLONGLONG 64 +#define SZPOINT(t) 32 + +/* + * Alignment constraints + */ +#define ALCHAR 8 +#define ALBOOL 32 +#define ALINT 32 +#define ALFLOAT 32 +#define ALDOUBLE 32 +#define ALLDOUBLE 32 +#define ALLONG 32 +#define ALLONGLONG 32 +#define ALSHORT 16 +#define ALPOINT 32 +#define ALSTRUCT 32 +#define ALSTACK 32 + +/* + * Min/max values. + */ +#define MIN_CHAR -128 +#define MAX_CHAR 127 +#define MAX_UCHAR 255 +#define MIN_SHORT -32768 +#define MAX_SHORT 32767 +#define MAX_USHORT 65535 +#define MIN_INT -1 +#define MAX_INT 0x7fffffff +#define MAX_UNSIGNED 0xffffffff +#define MIN_LONG MIN_INT +#define MAX_LONG MAX_INT +#define MAX_ULONG MAX_UNSIGNED +#define MIN_LONGLONG 0x8000000000000000LL +#define MAX_LONGLONG 0x7fffffffffffffffLL +#define MAX_ULONGLONG 0xffffffffffffffffULL + +#define BOOL_TYPE INT /* what used to store _Bool */ + +/* + * Use large-enough types. + */ +typedef long long CONSZ; +typedef unsigned long long U_CONSZ; +typedef long long OFFSZ; + +#define CONFMT "#%lld" /* format for printing constants */ +#define LABFMT ".L%d" /* format for printing labels */ +#define STABLBL "LL%d" /* format for stab (debugging) labels */ +#define STAB_LINE_ABSOLUTE /* S_LINE fields use absolute addresses */ + +#undef FIELDOPS /* no bit-field instructions */ + +#define ENUMSIZE(high,low) INT /* enums are always stored in full int */ + +/* Definitions mostly used in pass2 */ + +#define BYTEOFF(x) ((x)&03) +#define wdal(k) (BYTEOFF(k)==0) +#define BITOOR(x) (x) /* bit offset to oreg offset XXX die! */ + +#define STOARG(p) +#define STOFARG(p) +#define STOSTARG(p) + +#define szty(t) (((t) == DOUBLE || (t) == LDOUBLE || \ + (t) == LONGLONG || (t) == ULONGLONG) ? 2 : 1) + +#define R0 0 +#define R1 1 +#define R2 2 +#define R3 3 +#define R4 4 +#define R5 5 +#define R6 6 +#define R7 7 +#define R8 8 +#define R9 9 +#define R10 10 +#define R11 11 +#define R12 12 +#define R13 13 +#define R14 14 +#define R15 15 + +#define SL R10 +#define FP R11 +#define IP R12 +#define SP R13 +#define LR R14 +#define PC R15 + +#define R0R1 16 +#define R1R2 17 +#define R2R3 18 +#define R3R4 19 +#define R4R5 20 +#define R5R6 21 +#define R6R7 22 +#define R7R8 23 +#define R8R9 24 +#define R9R10 25 + +#define F0 26 +#define F1 27 +#define F2 28 +#define F3 29 +#define F4 30 +#define F5 31 +#define F6 32 +#define F7 33 + +#define NUMCLASS 3 +#define MAXREGS 34 + +#define RSTATUS \ + SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \ + SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, \ + SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, \ + 0, 0, 0, 0, 0, \ + SBREG|TEMPREG, SBREG|TEMPREG, SBREG|TEMPREG, SBREG, \ + SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \ + SCREG, SCREG, SCREG, SCREG, \ + SCREG, SCREG, SCREG, SCREG, \ + +#define ROVERLAP \ + { R0R1, -1 }, \ + { R0R1, R1R2, -1 }, \ + { R1R2, R2R3, -1 }, \ + { R2R3, R3R4, -1 }, \ + { R3R4, R4R5, -1 }, \ + { R4R5, R5R6, -1 }, \ + { R5R6, R6R7, -1 }, \ + { R6R7, R7R8, -1 }, \ + { R7R8, R8R9, -1 }, \ + { R8R9, R9R10, -1 }, \ + { R9R10, -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { R0, R1, R1R2, -1 }, \ + { R1, R2, R0R1, R2R3, -1 }, \ + { R2, R3, R1R2, R3R4, -1 }, \ + { R3, R4, R2R3, R4R5, -1 }, \ + { R4, R5, R3R4, R5R6, -1 }, \ + { R5, R6, R4R5, R6R7, -1 }, \ + { R6, R7, R5R6, R7R8, -1 }, \ + { R7, R8, R6R7, R8R9, -1 }, \ + { R8, R9, R7R8, R9R10, -1 }, \ + { R9, R10, R8R9, -1 }, \ + { -1, }, \ + { -1, }, \ + { -1, }, \ + { -1, }, \ + { -1, }, \ + { -1, }, \ + { -1, }, \ + { -1, }, \ + +#define BACKTEMP /* stack grows negatively for temporaries */ +#define BACKAUTO /* stack grows negatively for automatics */ + +#define ARGINIT (4*8) /* # bits above fp where arguments start */ +#define AUTOINIT (12*8) /* # bits above fp where automatics start */ + +#undef FIELDOPS /* no bit-field instructions */ +#define RTOLBYTES 1 /* bytes are numbered right to left */ + +/* XXX - to die */ +#define FPREG FP /* frame pointer */ + +/* Return a register class based on the type of the node */ +#define PCLASS(p) (1 << gclass((p)->n_type)) + +#define GCLASS(x) (x < 16 ? CLASSA : x < 26 ? CLASSB : CLASSC) +#define DECRA(x,y) (((x) >> (y*6)) & 63) /* decode encoded regs */ +#define ENCRD(x) (x) /* Encode dest reg in n_reg */ +#define ENCRA1(x) ((x) << 6) /* A1 */ +#define ENCRA2(x) ((x) << 12) /* A2 */ +#define ENCRA(x,y) ((x) << (6+y*6)) /* encode regs in int */ +#define RETREG(x) retreg(x) + +int COLORMAP(int c, int *r); +int retreg(int ty); +int features(int f); + +#define FEATURE_BIGENDIAN 0x00010000 +#define FEATURE_HALFWORDS 0x00020000 /* ldrsh/ldrh, ldrsb */ +#define FEATURE_EXTEND 0x00040000 /* sxth, sxtb, uxth, uxtb */ +#define FEATURE_MUL 0x00080000 +#define FEATURE_MULL 0x00100000 +#define FEATURE_FPA 0x10000000 +#define FEATURE_VFP 0x20000000 +#define FEATURE_HARDFLOAT (FEATURE_FPA|FEATURE_VFP) + +#define TARGET_STDARGS +#define TARGET_BUILTINS \ + { "__builtin_stdarg_start", arm_builtin_stdarg_start }, \ + { "__builtin_va_arg", arm_builtin_va_arg }, \ + { "__builtin_va_end", arm_builtin_va_end }, \ + { "__builtin_va_copy", arm_builtin_va_copy }, + +#define NODE struct node +struct node; +NODE *arm_builtin_stdarg_start(NODE *f, NODE *a); +NODE *arm_builtin_va_arg(NODE *f, NODE *a); +NODE *arm_builtin_va_end(NODE *f, NODE *a); +NODE *arm_builtin_va_copy(NODE *f, NODE *a); +#undef NODE + +#define COM "\t@ " +#define NARGREGS 4 diff --git a/compilers/pcc/pcc-1.0.0/arch/arm/order.c b/compilers/pcc/pcc-1.0.0/arch/arm/order.c new file mode 100644 index 00000000..021bc465 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/arm/order.c @@ -0,0 +1,339 @@ +/* $Id: order.c,v 1.9 2008/09/27 07:35:22 ragge Exp $ */ +/* + * Copyright (c) 2007 Gregory McGarry (g.mcgarry@ieee.org). + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Machine-dependent code-generation strategy (pass 2). + */ + +#include +#include + +#include "pass2.h" + +/* + * Check size of offset in OREG. Called by oregok() to see if an + * OREG can be generated. + */ +int +notoff(TWORD ty, int r, CONSZ off, char *cp) +{ + if (cp && cp[0]) return 1; + if (DEUNSIGN(ty) == INT || ty == UCHAR) + return !(off < 4096 && off > -4096); + else + return !(off < 256 && off > -256); +} + +/* + * Generate instructions for an OREG. Why is this routine MD? + * Called by swmatch(). + */ +void +offstar(NODE *p, int shape) +{ + NODE *r; + + if (isreg(p)) + return; /* Is already OREG */ + + r = p->n_right; + if( p->n_op == PLUS || p->n_op == MINUS ){ + if( r->n_op == ICON ){ + if (isreg(p->n_left) == 0) + (void)geninsn(p->n_left, INAREG); + /* Converted in ormake() */ + return; + } + /* usually for arraying indexing: */ + if (r->n_op == LS && r->n_right->n_op == ICON && + r->n_right->n_lval == 2 && p->n_op == PLUS) { + if (isreg(p->n_left) == 0) + (void)geninsn(p->n_left, INAREG); + if (isreg(r->n_left) == 0) + (void)geninsn(r->n_left, INAREG); + return; + } + } + (void)geninsn(p, INAREG); +} + +/* + * Unable to convert to OREG (notoff() returned failure). Output + * suitable instructions to replace OREG. + */ +void +myormake(NODE *q) +{ + NODE *p, *r; + + if (x2debug) + printf("myormake(%p)\n", q); + + p = q->n_left; + + /* + * This handles failed OREGs conversions, due to the offset + * being too large for an OREG. + */ + if ((p->n_op == PLUS || p->n_op == MINUS) && p->n_right->n_op == ICON) { + if (isreg(p->n_left) == 0) + (void)geninsn(p->n_left, INAREG); + if (isreg(p->n_right) == 0) + (void)geninsn(p->n_right, INAREG); + (void)geninsn(p, INAREG); + } else if (p->n_op == REG) { + q->n_op = OREG; + q->n_lval = p->n_lval; + q->n_rval = p->n_rval; + tfree(p); + } else if (p->n_op == PLUS && (r = p->n_right)->n_op == LS && + r->n_right->n_op == ICON && r->n_right->n_lval == 2 && + p->n_left->n_op == REG && r->n_left->n_op == REG) { + q->n_op = OREG; + q->n_lval = 0; + q->n_rval = R2PACK(p->n_left->n_rval, r->n_left->n_rval, + r->n_right->n_lval); + tfree(p); + } +} + +/* + * Check to if the UMUL node can be converted into an OREG. + */ +int +shumul(NODE *p, int shape) +{ + /* Turns currently anything into OREG */ + if (shape & SOREG) + return SROREG; + return SRNOPE; +} + +/* + * Rewrite operations on binary operators (like +, -, etc...). + * Called as a result of a failed table lookup. + * + * Return nonzero to retry table search on new tree, or zero to fail. + */ +int +setbin(NODE *p) +{ + return 0; + +} + +/* + * Rewrite assignment operations. + * Called as a result of a failed table lookup. + * + * Return nonzero to retry table search on new tree, or zero to fail. + */ +int +setasg(NODE *p, int cookie) +{ + return 0; +} + +/* + * Rewrite UMUL operation. + * Called as a result of a failed table lookup. + * + * Return nonzero to retry table search on new tree, or zero to fail. + */ +int +setuni(NODE *p, int cookie) +{ + return 0; +} + +/* + * Special handling of some instruction register allocation. + * + * Called as a result of specifying NSPECIAL in the table. + */ +struct rspecial * +nspecial(struct optab *q) +{ + + switch (q->op) { + +#if !defined(ARM_HAS_FPA) && !defined(ARM_HAS_VFP) + case UMINUS: + case SCONV: + if (q->lshape == SBREG && q->rshape == SAREG) { + static struct rspecial s[] = { + { NLEFT, R0R1 }, + { NRES, R0 }, + { 0 } + }; + return s; + } else if (q->lshape == SAREG && q->rshape == SBREG) { + static struct rspecial s[] = { + { NLEFT, R0 }, + { NRES, R0R1 }, + { 0 } + }; + return s; + } else if (q->lshape == SAREG && q->rshape == SAREG) { + static struct rspecial s[] = { + { NLEFT, R0 }, + { NRES, R0 }, + { 0 } + }; + return s; + } else if (q->lshape == SBREG && q->rshape == SBREG) { + static struct rspecial s[] = { + { NLEFT, R0R1 }, + { NRES, R0R1 }, + { 0 } + }; + return s; + } + + case OPLOG: + if (q->lshape == SBREG) { + static struct rspecial s[] = { + { NLEFT, R0R1 }, + { NRIGHT, R2R3 }, + { NRES, R0 }, + { 0 } + }; + return s; + } else if (q->lshape == SAREG) { + static struct rspecial s[] = { + { NLEFT, R0 }, + { NRIGHT, R1 }, + { NRES, R0 }, + { 0 } + }; + return s; + } + case PLUS: + case MINUS: + case MUL: +#endif + case MOD: + case DIV: + if (q->lshape == SBREG) { + static struct rspecial s[] = { + { NLEFT, R0R1 }, + { NRIGHT, R2R3 }, + { NRES, R0R1 }, + { 0 } + }; + return s; + } else if (q->lshape == SAREG) { + static struct rspecial s[] = { + { NLEFT, R0 }, + { NRIGHT, R1 }, + { NRES, R0 }, + { 0 } + }; + return s; + } + case LS: + case RS: + if (q->lshape == SBREG) { + static struct rspecial s[] = { + { NLEFT, R0R1 }, + { NRIGHT, R2 }, + { NRES, R0R1 }, + { 0 } + }; + return s; + } else if (q->lshape == SAREG) { + static struct rspecial s[] = { + { NLEFT, R0 }, + { NRIGHT, R1 }, + { NRES, R0 }, + { 0 } + }; + return s; + } + case STASG: + { + static struct rspecial s[] = { + { NEVER, R0 }, + { NRIGHT, R1 }, + { NEVER, R2 }, + { 0 } }; + return s; + } + break; + + default: + break; + } + +#ifdef PCC_DEBUG + comperr("nspecial entry %d [0x%x]: %s", q - table, q->op, q->cstring); +#endif + return 0; /* XXX gcc */ +} + +/* + * Set evaluation order of a binary node ('+','-', '*', '/', etc) if it + * differs from default. + */ +int +setorder(NODE *p) +{ + return 0; +} + +/* + * Set registers "live" at function calls (like arguments in registers). + * This is for liveness analysis of registers. + */ +int * +livecall(NODE *p) +{ + static int r[] = { R3, R2, R1, R0, -1 }; + int num = 1; + + if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL) + return &r[4-0]; + + for (p = p->n_right; p->n_op == CM; p = p->n_left) + num += szty(p->n_right->n_type); + num += szty(p->n_right->n_type); + + num = (num > 4 ? 4 : num); + + return &r[4 - num]; +} + +/* + * Signal whether the instruction is acceptable for this target. + */ +int +acceptable(struct optab *op) +{ + return features(op->visit & 0xffff0000); +} diff --git a/compilers/pcc/pcc-1.0.0/arch/arm/table.c b/compilers/pcc/pcc-1.0.0/arch/arm/table.c new file mode 100644 index 00000000..70e57189 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/arm/table.c @@ -0,0 +1,1847 @@ +/* $Id: table.c,v 1.19 2008/05/16 02:20:36 gmcgarry Exp $ */ +/*- + * Copyright (c) 2007 Gregory McGarry + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * A template has five logical sections: + * + * 1) subtree (operator); goal to achieve (cookie) + * 2) left node descendent of operator (node class; type) + * 3) right node descendent of operator (node class; type) + * 4) resource requirements (number of scratch registers); + * subtree rewriting rule + * 5) emitted instructions + */ + +#include "pass2.h" + +#define TUWORD TUNSIGNED|TULONG +#define TSWORD TINT|TLONG +#define TWORD TUWORD|TSWORD + +struct optab table[] = { +/* First entry must be an empty entry */ +{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", }, + +/* PCONVs are not necessary */ +{ PCONV, INAREG, + SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + 0, RLEFT, + COM "pointer conversion\n", }, + + +/* + * Conversions of integral types + * + * For each deunsigned type, they look something like this: + * + * signed -> bigger signed - nothing to do + * signed -> bigger unsigned - clear the top bits (of source type) + * + * signed -> smaller signed - sign-extend the bits (to dest type) + * signed -> smaller unsigned - clear the top bits (of dest type) + * unsigned -> smaller signed - sign-extend top bits (to dest type) + * unsigned -> smaller unsigned - clear the top bits (of dest type) + * + * unsigned -> bigger - nothing to do + */ + +{ SCONV, INAREG, + SAREG, TCHAR, + SAREG, TSWORD|TSHORT, + 0, RLEFT, + COM "convert char to short/int\n", }, + +{ SCONV, INAREG, + SAREG, TCHAR, + SAREG, TUWORD|TUSHORT|TUCHAR, + NAREG|NASL, RESC1, + " and A1,AL,#255" COM "convert char to uchar/ushort/uint\n", }, + +{ SCONV, INAREG | FEATURE_EXTEND, + SAREG, TUCHAR, + SAREG, TCHAR, + NAREG|NASL, RESC1, + " sxtb A1,AL" COM "convert uchar to char\n", }, + +{ SCONV, INAREG, + SAREG, TUCHAR, + SAREG, TCHAR, + NAREG|NASL, RESC1, + " mov A1,AL,asl #24" COM "convert uchar to char\n" + " mov A1,A1,asr #24\n", }, + +{ SCONV, INAREG, + SAREG, TUCHAR, + SAREG, TWORD|TSHORT|TUSHORT, + 0, RLEFT, + COM "convert uchar to (u)short/(u)int\n", }, + +{ SCONV, INAREG, + SAREG, TSHORT, + SAREG, TSWORD, + 0, RLEFT, + COM "convert short to int\n", }, + +{ SCONV, INAREG | FEATURE_EXTEND, + SAREG, TSHORT, + SAREG, TUWORD|TUSHORT, + NAREG|NASL, RESC1, + " uxth A1,AL" COM "convert short to uint\n", }, + +{ SCONV, INAREG, + SAREG, TSHORT, + SAREG, TUWORD|TUSHORT, + NAREG|NASL, RESC1, + " mov A1,AL,asl #16" COM "convert short to uint\n" + " mov A1,AL,lsr #16\n", }, + +{ SCONV, INAREG | FEATURE_EXTEND, + SAREG, TUSHORT, + SAREG, TSHORT, + NAREG|NASL, RESC1, + " sxth A1,AL" COM "convert ushort to short\n", }, + +{ SCONV, INAREG, + SAREG, TUSHORT, + SAREG, TSHORT, + NAREG|NASL, RESC1, + " mov A1,AL,asl #16" COM "convert ushort to short\n" + " mov A1,A1,asr #16\n", }, + +{ SCONV, INAREG | FEATURE_EXTEND, + SAREG, TSHORT|TUSHORT, + SAREG, TCHAR, + NAREG|NASL, RESC1, + " sxtb A1,AL" COM "convert (u)short to char\n", }, + +{ SCONV, INAREG, + SAREG, TSHORT|TUSHORT, + SAREG, TCHAR, + NAREG|NASL, RESC1, + " mov A1,AL,asl #24" COM "convert (u)short to char\n" + " mov A1,A1,asr #24\n", }, + +{ SCONV, INAREG, + SAREG, TSHORT|TUSHORT, + SAREG, TCHAR, + NAREG|NASL, RESC1, + " sxtb A1,AL" COM "convert (u)short to char\n", }, + +{ SCONV, INAREG, + SAREG, TSHORT|TUSHORT, + SAREG, TUCHAR, + NAREG|NASL, RESC1, + " and A1,AL,#255" COM "convert (u)short to uchar\n", }, + +{ SCONV, INAREG, + SAREG, TUSHORT, + SAREG, TWORD, + 0, RLEFT, + COM "convert ushort to (u)int\n", }, + +{ SCONV, INAREG | FEATURE_EXTEND, + SAREG, TWORD, + SAREG, TCHAR, + NAREG|NASL, RESC1, + " sxtb A1,AL" COM "convert (u)int to char\n", }, + +{ SCONV, INAREG, + SAREG, TWORD, + SAREG, TCHAR, + NAREG|NASL, RESC1, + " mov A1,AL,asl #24" COM "convert (u)int to char\n" + " mov A1,A1,asr #24\n", }, + +{ SCONV, INAREG | FEATURE_EXTEND, + SAREG, TWORD, + SAREG, TSHORT, + NAREG|NASL, RESC1, + " sxth A1,AL" COM "convert (u)int to short\n", }, + +{ SCONV, INAREG, + SAREG, TWORD, + SAREG, TSHORT, + NAREG|NASL, RESC1, + " mov A1,AL,asl #16" COM "convert (u)int to short\n" + " mov A1,A1,asr #16\n", }, + +{ SCONV, INAREG, + SAREG, TWORD, + SAREG, TUCHAR, + NAREG|NASL, RESC1, + " and A1,AL,#255" COM "convert uchar to char\n", }, + +{ SCONV, INAREG | FEATURE_EXTEND, + SAREG, TWORD, + SAREG, TUSHORT, + NAREG|NASL, RESC1, + " uxth A1,AL" COM "convert int to ushort\n", }, + +{ SCONV, INAREG, + SAREG, TWORD, + SAREG, TUSHORT, + NAREG|NASL, RESC1, + " mov A1,AL,asl #16" COM "convert int to ushort\n" + " mov A1,AL,lsr #16\n", }, + +{ SCONV, INAREG, + SAREG, TPOINT|TWORD, + SAREG, TWORD|TPOINT, + 0, RLEFT, + COM "convert between pointers and words\n", }, + +{ SCONV, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + 0, RLEFT, + COM "convert (u)longlong to (u)longlong\n", }, + +/* convert (u)char/(u)short/(u)int to longlong */ +{ SCONV, INBREG, + SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + SBREG, TLONGLONG|TULONGLONG, + NBREG|NBSL, RESC1, + " mov A1,AL" COM "convert (u)char/(u)short/(u)int to (u)longlong\n" + " mov U1,AL,asr #31\n", }, + +{ SCONV, INAREG | FEATURE_EXTEND, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TCHAR, + NAREG, RESC1, + " sxtb A1,AL" COM "convert (u)longlong to char\n", }, + +{ SCONV, INAREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TCHAR, + NAREG, RESC1, + " mov A1,AL,asl #24" COM "convert (u)longlong to char\n" + " mov A1,A1,asr #24\n", }, + +{ SCONV, INAREG | FEATURE_EXTEND, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TSHORT, + NAREG, RESC1, + " sxth A1,AL" COM "convert (u)longlong to short\n", }, + +{ SCONV, INAREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TSHORT, + NAREG, RESC1, + " mov A1,AL,asl #16" COM "convert (u)longlong to short\n" + " mov A1,A1,asr #16\n", }, + +{ SCONV, INAREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TWORD, + NAREG, RESC1, + " mov A1,AL" COM "convert (u)longlong to (u)int\n", }, + +{ SCONV, INAREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TUCHAR, + NAREG, RESC1, + " and A1,AL,#255" COM "convert (u)longlong to uchar\n", }, + +{ SCONV, INAREG | FEATURE_EXTEND, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TUSHORT, + NAREG, RESC1, + " uxth A1,AL" COM "convert (u)longlong to ushort\n", }, + +{ SCONV, INAREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TUSHORT, + NAREG, RESC1, + " mov A1,AL,asl #16" COM "convert (u)longlong to ushort\n" + " mov A1,A1,lsr #16\n", }, + +/* conversions on load from memory */ + +/* char */ +{ SCONV, INAREG, + SOREG, TCHAR, + SAREG, TWORD, + NASL|NAREG, RESC1, + " ldrsb A1,AL" COM "convert char to int/long\n", }, + +/* uchar */ +{ SCONV, INAREG, + SOREG, TUCHAR, + SAREG, TWORD, + NASL|NAREG, RESC1, + " ldrb A1,AL" COM "convert uchar to int/long\n", }, + +/* short */ +{ SCONV, INAREG | FEATURE_HALFWORDS, + SOREG, TSHORT, + SAREG, TWORD, + NASL|NAREG, RESC1, + " ldrsh A1,AL" COM "convert short to int/long\n", }, + +/* ushort */ +{ SCONV, INAREG | FEATURE_HALFWORDS, + SOREG, TSHORT, + SAREG, TWORD, + NASL|NAREG, RESC1, + " ldrh A1,AL" COM "convert ushort to int/long\n", }, + +/* short */ +{ SCONV, INAREG, + SOREG, TSHORT|TUSHORT, + SAREG, TWORD, + 2*NAREG|NASL, RESC1, + "ZH", }, + +{ SCONV, INAREG | FEATURE_FPA, + SCREG, TFLOAT, + SAREG, TWORD, + NAREG, RESC1, + " fix AL,AR" COM "convert float to int\n", }, + +{ SCONV, INAREG | FEATURE_VFP, + SCREG, TFLOAT, + SAREG, TSWORD, + NAREG, RESC1, + " ftosis AL,AR" COM "convert float to int\n", }, + +{ SCONV, INAREG | FEATURE_VFP, + SCREG, TFLOAT, + SAREG, TSWORD, + NAREG, RESC1, + " ftouis AL,AR" COM "convert float to int\n", }, + +{ SCONV, INAREG, + SAREG, TFLOAT, + SAREG, TWORD, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +{ SCONV, INBREG | FEATURE_FPA, + SCREG, TFLOAT, + SBREG, TULONGLONG|TLONGLONG, + NBREG, RESC1, + COM "unimplemented\n", }, + +{ SCONV, INBREG | FEATURE_VFP, + SCREG, TFLOAT, + SBREG, TULONGLONG|TLONGLONG, + NBREG, RESC1, + COM "unimplemented\n", }, + +{ SCONV, INBREG, + SAREG, TFLOAT, + SBREG, TULONGLONG|TLONGLONG, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +{ SCONV, INAREG | FEATURE_FPA, + SCREG, TDOUBLE|TLDOUBLE, + SAREG, TWORD, + NAREG, RESC1, + " fix AL,AR" COM "convert double/ldouble to int\n", }, + +{ SCONV, INAREG | FEATURE_VFP, + SCREG, TDOUBLE|TLDOUBLE, + SAREG, TSWORD, + NAREG, RESC1, + " ftosid AL,AR" COM "convert double/ldouble to int\n", }, + +{ SCONV, INAREG | FEATURE_VFP, + SCREG, TDOUBLE|TLDOUBLE, + SAREG, TUWORD, + NAREG, RESC1, + " ftouid AL,AR" COM "convert double/ldouble to int\n", }, + +{ SCONV, INAREG, + SBREG, TDOUBLE|TLDOUBLE, + SAREG, TWORD, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +{ SCONV, INBREG | FEATURE_FPA, + SCREG, TDOUBLE|TLDOUBLE, + SBREG, TLONGLONG|TULONGLONG, + NBREG, RESC1, + COM "unimplemented\n", }, + +{ SCONV, INBREG | FEATURE_VFP, + SCREG, TDOUBLE|TLDOUBLE, + SBREG, TULONGLONG|TLONGLONG, + NBREG, RESC1, + COM "unimplemented\n", }, + +{ SCONV, INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SBREG, TULONGLONG|TLONGLONG, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +{ SCONV, INCREG | FEATURE_FPA, + SAREG, TWORD, + SCREG, TFLOAT, + NCREG, RESC1, + " flts AL,AR" COM "convert int to float\n" }, + +{ SCONV, INCREG | FEATURE_VFP, + SAREG, TSWORD, + SCREG, TFLOAT, + NCREG, RESC1, + " fsitos AL,AR" COM "convert int to float\n" }, + +{ SCONV, INCREG | FEATURE_VFP, + SAREG, TUWORD, + SCREG, TFLOAT, + NCREG, RESC1, + " fuitos AL,AR" COM "convert int to float\n" }, + +{ SCONV, INAREG, + SAREG, TWORD, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +{ SCONV, INCREG | FEATURE_FPA, + SBREG, TULONGLONG|TLONGLONG, + SCREG, TFLOAT, + NCREG, RESC1, + COM "unimplemented\n", }, + +{ SCONV, INCREG | FEATURE_VFP, + SBREG, TULONGLONG|TLONGLONG, + SCREG, TFLOAT, + NCREG, RESC1, + COM "unimplemented\n", }, + +{ SCONV, INAREG, + SBREG, TULONGLONG|TLONGLONG, + SAREG, TFLOAT, + NAREG, RESC1, + COM "unimplemented\n", }, + +{ SCONV, INCREG | FEATURE_FPA, + SAREG, TWORD, + SCREG, TDOUBLE, + NCREG, RESC1, + " fltd AL,AR" COM "convert int to double\n" }, + +{ SCONV, INCREG | FEATURE_VFP, + SAREG, TSWORD, + SCREG, TDOUBLE, + NCREG, RESC1, + " fsitod AL,AR" COM "convert int to double\n" }, + +{ SCONV, INCREG | FEATURE_VFP, + SAREG, TUWORD, + SCREG, TDOUBLE, + NCREG, RESC1, + " fuitod AL,AR" COM "convert int to double\n" }, + +{ SCONV, INBREG, + SAREG, TWORD, + SBREG, TDOUBLE, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +{ SCONV, INCREG | FEATURE_FPA, + SBREG, TLONGLONG|TULONGLONG, + SCREG, TDOUBLE, + NCREG, RESC1, + COM "unimplemented\n", }, + +{ SCONV, INCREG | FEATURE_VFP, + SBREG, TLONGLONG|TULONGLONG, + SCREG, TDOUBLE, + NCREG, RESC1, + COM "unimplemented\n", }, + +{ SCONV, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TDOUBLE, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +{ SCONV, INCREG | FEATURE_FPA, + SAREG, TWORD, + SCREG, TLDOUBLE, + NCREG, RESC1, + " flte AL,AR" COM "convert int to ldouble\n" }, + +{ SCONV, INCREG | FEATURE_VFP, + SAREG, TSWORD, + SCREG, TLDOUBLE, + NCREG, RESC1, + " fsitod AL,AR" COM "convert int to ldouble\n" }, + +{ SCONV, INCREG | FEATURE_VFP, + SAREG, TUWORD, + SCREG, TLDOUBLE, + NCREG, RESC1, + " fuitod AL,AR" COM "convert uint to ldouble\n" }, + +{ SCONV, INBREG, + SAREG, TWORD, + SBREG, TLDOUBLE, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +{ SCONV, INCREG | FEATURE_FPA, + SBREG, TLONGLONG|TULONGLONG, + SCREG, TLDOUBLE, + NCREG, RESC1, + COM "unimplemented\n", }, + +{ SCONV, INCREG | FEATURE_VFP, + SBREG, TLONGLONG|TULONGLONG, + SCREG, TLDOUBLE, + NCREG, RESC1, + COM "unimplemented\n", }, + +{ SCONV, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLDOUBLE, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +{ SCONV, INCREG | FEATURE_FPA, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TFLOAT, + NCREG, RESC1, + COM "unimplemented\n", }, + +{ SCONV, INCREG | FEATURE_VFP, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TFLOAT, + NCREG, RESC1, + " fcvtds AL,AR" COM "convert float to double\n" }, + +{ SCONV, INAREG, + SBREG, TDOUBLE|TLDOUBLE, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +{ SCONV, INCREG | FEATURE_FPA, + SCREG, TFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + NCREG, RESC1, + COM "unimplemented\n", }, + +{ SCONV, INCREG | FEATURE_VFP, + SCREG, TFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + NCREG, RESC1, + " fcvtsd AL,AR" COM "convert float to double\n" }, + +{ SCONV, INBREG, + SAREG, TFLOAT, + SBREG, TDOUBLE|TLDOUBLE, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +{ SCONV, INCREG | FEATURE_FPA, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + 0, RLEFT, + COM "convert (l)double to (l)double", }, + +{ SCONV, INCREG | FEATURE_VFP, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + 0, RLEFT, + COM "convert (l)double to (l)double", }, + +{ SCONV, INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SBREG, TDOUBLE|TLDOUBLE, + 0, RLEFT, + COM "convert (l)double to (l)double", }, + +/* + * Subroutine calls. + */ + +{ CALL, FOREFF, + SCON|SNAME, TANY, + SANY, TANY, + 0, 0, + " bl CL" COM "call (args, no result) to scon/sname (CL)\n" + "ZC", }, + +{ UCALL, FOREFF, + SCON|SNAME, TANY, + SANY, TANY, + 0, 0, + " bl CL" COM "call (no args, no result) to scon/sname (CL)\n", }, + +{ CALL, INAREG, + SCON|SNAME, TANY, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, /* should be 0 */ + " bl CL" COM "call (args, result in r0) to scon/sname (CL)\n" + "ZC", }, + +{ CALL, INBREG, + SCON|SNAME, TANY, + SBREG, TLONGLONG|TULONGLONG, + NBREG|NBSL, RESC1, /* should be 0 */ + " bl CL" COM "call (args, result in r0:r1) to scon/sname (CL)\n" + "ZC", }, + +{ CALL, INCREG | FEATURE_FPA, + SCON|SNAME, TANY, + SCREG, TFLOAT, + NCREG|NCSL, RESC1, /* should be 0 */ + " bl CL" COM "call (args, result r0) to scon/sname (CL)\n" + "ZC", }, + +{ CALL, INCREG | FEATURE_FPA, + SCON|SNAME, TANY, + SCREG, TDOUBLE|TLDOUBLE, + NCREG|NCSL, RESC1, /* should be 0 */ + " bl CL" COM "call (args, result in r0:r1) to scon/sname (CL)\n" + "ZC", }, + +{ CALL, INAREG, + SCON|SNAME, TANY, + SAREG, TFLOAT, + NAREG|NASL, RESC1, /* should be 0 */ + " bl CL" COM "call (args, result r0) to scon/sname (CL)\n" + "ZC", }, + +{ CALL, INBREG, + SCON|SNAME, TANY, + SBREG, TDOUBLE|TLDOUBLE, + NBREG|NBSL, RESC1, /* should be 0 */ + " bl CL" COM "call (args, result in r0:r1) to scon/sname (CL)\n" + "ZC", }, + +{ UCALL, INAREG, + SCON|SNAME, TANY, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, /* should be 0 */ + " bl CL" COM "call (no args, result in r0) to scon/sname (CL)\n", }, + +{ UCALL, INBREG, + SCON|SNAME, TANY, + SBREG, TLONGLONG|TULONGLONG, + NBREG|NBSL, RESC1, /* should be 0 */ + " bl CL" COM "call (no args, result in r0:r1) to scon/sname (CL)\n", }, + +{ UCALL, INCREG | FEATURE_FPA, + SCON|SNAME, TANY, + SCREG, TFLOAT, + NCREG|NCSL, RESC1, /* should be 0 */ + " bl CL" COM "call (no args, result in r0) to scon/sname (CL)\n", }, + +{ UCALL, INCREG | FEATURE_FPA, + SCON|SNAME, TANY, + SCREG, TDOUBLE|TLDOUBLE, + NCREG|NCSL, RESC1, /* should be 0 */ + " bl CL" COM "call (no args, result in r0:r1) to scon/sname (CL)\n", }, + +{ CALL, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, 0, + " mov lr,pc\n" + " mov pc,AL\n" + "ZC", }, + +{ UCALL, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, 0, + " mov lr,pc\n" + " mov pc,AL\n", }, + +{ CALL, INAREG, + SAREG, TANY, + SANY, TANY, + NAREG, RESC1, + " mov lr,pc\n" + " mov pc,AL\n" + "ZC", }, + +{ UCALL, INAREG, + SAREG, TANY, + SANY, TANY, + NAREG, RESC1, + " mov lr,pc\n" + " mov pc,AL\n", }, + +{ CALL, INBREG, + SAREG, TANY, + SANY, TANY, + NBREG, RESC1, + " mov lr,pc\n" + " mov pc,AL\n" + "ZC", }, + +{ UCALL, INBREG, + SAREG, TANY, + SANY, TANY, + NBREG, RESC1, + " mov lr,pc\n" + " mov pc,AL\n", }, + +/* struct return */ +{ USTCALL, FOREFF, + SCON, TANY, + SANY, TANY, + 0, 0, + " bl CL\n", }, + +{ USTCALL, INAREG, + SCON, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + " bl CL\n", }, + +{ USTCALL, INAREG, + SNAME|SAREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + " mov lr,pc\n" + " mov pc,AL\n", }, + +{ STCALL, FOREFF, + SCON, TANY, + SANY, TANY, + 0, 0, + " bl CL\n" + "ZC", }, + +{ STCALL, INAREG, + SCON, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + " bl CL\n" + "ZC", }, + +{ STCALL, INAREG, + SNAME|SAREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + " mov lr,pc\n" + " mov pc,AL\n" + "ZC", }, + +/* + * The next rules handle all binop-style operators. + */ + +{ PLUS, INAREG, + SAREG, TWORD|TPOINT, + SCCON, TANY, + NAREG, RESC1, + " add A1,AL,AR" COM "addition of constant\n", }, + +{ PLUS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SSCON, TANY, + NBREG|NBSL, RESC1, + " adds A1,AL,AR" COM "64-bit addition of constant\n" + " adc U1,UL,UR\n", }, + +{ PLUS, INAREG, + SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + NAREG|NASL, RESC1, + " add A1,AL,AR" COM "addition\n", }, + +{ PLUS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NBREG|NBSL, RESC1, + " adds A1,AL,AR" COM "64-bit addition\n" + " adc U1,UL,UR\n", }, + +{ PLUS, INCREG | FEATURE_FPA, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, + " adfs A1,AL,AR" COM "float add\n", }, + +{ PLUS, INCREG | FEATURE_VFP, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, + " fadds A1,AL,AR" COM "float add\n", }, + +{ PLUS, INAREG, + SAREG, TFLOAT, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +{ PLUS, INCREG | FEATURE_FPA, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG, RESC1, + " adfd A1,AL,AR" COM "double add\n", }, + +{ PLUS, INCREG | FEATURE_VFP, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG, RESC1, + " faddd A1,AL,AR" COM "double add\n", }, + +{ PLUS, INBREG, + SBREG, TDOUBLE, + SBREG, TDOUBLE, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +{ PLUS, INCREG | FEATURE_FPA, + SCREG, TLDOUBLE, + SCREG, TLDOUBLE, + NCREG, RESC1, + " adfe A1,AL,AR" COM "ldouble add\n", }, + +{ PLUS, INCREG | FEATURE_VFP, + SCREG, TLDOUBLE, + SCREG, TLDOUBLE, + NCREG, RESC1, + " faddd A1,AL,AR" COM "ldouble add\n", }, + +{ PLUS, INBREG, + SBREG, TLDOUBLE, + SBREG, TLDOUBLE, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +{ MINUS, INAREG, + SAREG, TWORD|TPOINT, + SCCON, TANY, + NAREG|NASL, RESC1, + " sub A1,AL,AR" COM "subtraction of constant\n", }, + +{ MINUS, INAREG, + SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + NAREG|NASL, RESC1, + " sub A1,AL,AR" COM "subtraction\n", }, + +{ MINUS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SCCON, TANY, + NBREG|NBSL, RESC1, + " subs A1,AL,AR" COM "64-bit subtraction of constant\n" + " rsc U1,UL,AR\n", }, + +{ MINUS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NBREG|NBSL, RESC1, + " subs A1,AL,AR" COM "64-bit subtraction\n" + " sbc U1,UL,AR\n", }, + +{ MINUS, INCREG | FEATURE_FPA, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, + " sufs A1,AL,AR" COM "float subtraction\n", }, + +{ MINUS, INCREG | FEATURE_VFP, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, + " fsubs A1,AL,AR" COM "float subtraction\n", }, + +{ MINUS, INAREG, + SAREG, TFLOAT, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +{ MINUS, INCREG | FEATURE_FPA, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG, RESC1, + " sufd A1,AL,AR" COM "double subtraction\n", }, + +{ MINUS, INCREG | FEATURE_VFP, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG, RESC1, + " fsubd A1,AL,AR" COM "double subtraction\n", }, + +{ MINUS, INBREG, + SBREG, TDOUBLE, + SBREG, TDOUBLE, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +{ MINUS, INCREG | FEATURE_FPA, + SCREG, TLDOUBLE, + SCREG, TLDOUBLE, + NCREG, RESC1, + " sufe A1,AL,AR" COM "ldouble subtraction\n", }, + +{ MINUS, INCREG | FEATURE_VFP, + SCREG, TLDOUBLE, + SCREG, TLDOUBLE, + NCREG, RESC1, + " fsubd A1,AL,AR" COM "double subtraction\n", }, + +{ MINUS, INBREG, + SBREG, TLDOUBLE, + SBREG, TLDOUBLE, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +/* + * The next rules handle all shift operators. + */ + +{ LS, INAREG, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TANY, + NAREG|NASL, RESC1, + " mov A1,AL,asl AR" COM "left shift\n", }, + +{ LS, INAREG, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SCCON, TANY, + NAREG|NASL, RESC1, + " mov A1,AL,asl AR" COM "left shift by constant\n", }, + +{ LS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SCON, TANY, + NBREG, RESC1, + "ZO" }, + +{ LS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TANY, + NSPECIAL|NBREG, RESC1, + "ZE" }, + +{ RS, INAREG, + SAREG, TSWORD|TSHORT|TCHAR, + SAREG, TANY, + NAREG|NASL, RESC1, + " mov A1,AL,asr AR" COM "right shift\n", }, + +{ RS, INAREG, + SAREG, TUWORD|TUSHORT|TUCHAR, + SAREG, TANY, + NAREG|NASL, RESC1, + " mov A1,AL,lsr AR" COM "right shift\n", }, + +{ RS, INAREG, + SAREG, TSWORD|TSHORT|TCHAR, + SCCON, TANY, + NAREG|NASL, RESC1, + " mov A1,AL,asr AR" COM "right shift by constant\n", }, + +{ RS, INAREG, + SAREG, TUWORD|TUSHORT|TUCHAR, + SCCON, TANY, + NAREG|NASL, RESC1, + " mov A1,AL,lsr AR" COM "right shift by constant\n", }, + +{ RS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SCON, TANY, + NBREG, RESC1, + "ZO" }, + +{ RS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TANY, + NSPECIAL|NBREG, RESC1, + "ZE" }, + + +/* + * The next rules takes care of assignments. "=". + */ + +{ ASSIGN, FOREFF|INAREG, + SOREG|SNAME, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + 0, RDEST, + " str AR,AL" COM "assign word\n", }, + +{ ASSIGN, FOREFF|INBREG, + SOREG|SNAME, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + 0, RDEST, + " str AR,AL" COM "assign 64-bit value\n" + " str UR,UL\n", }, + +/* XXX don't know if this works */ +{ ASSIGN, FOREFF|INBREG, + SAREG, TPTRTO|TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + 0, RDEST, + " stmdb AL,{AR-UR}" COM "assign 64-bit value\n", }, + +{ ASSIGN, FOREFF|INAREG, + SOREG|SNAME, TCHAR|TUCHAR, + SAREG, TCHAR|TUCHAR, + 0, RDEST, + " strb AR,AL" COM "assign (u)char\n", }, + +{ ASSIGN, FOREFF|INAREG | FEATURE_HALFWORDS, + SOREG|SNAME, TSHORT|TUSHORT, + SAREG, TSHORT|TUSHORT, + 0, RDEST, + " strh AR,AL" COM "assign (u)short\n", }, + +{ ASSIGN, FOREFF|INAREG, + SOREG|SNAME, TSHORT|TUSHORT, + SAREG, TSHORT|TUSHORT, + NAREG|NASL, RDEST, + "ZH", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_FPA, + SOREG|SNAME, TFLOAT, + SCREG, TFLOAT, + 0, RDEST, + " stfs AR,AL" COM "assign float\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_VFP, + SOREG|SNAME, TFLOAT, + SCREG, TFLOAT, + 0, RDEST, + COM "unimplemented\n", }, + +{ ASSIGN, FOREFF|INAREG, + SOREG|SNAME, TFLOAT, + SAREG, TFLOAT, + 0, RDEST, + " str AR,AL" COM "assign float (soft-float)\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_FPA, + SOREG|SNAME, TDOUBLE, + SCREG, TDOUBLE, + 0, RDEST, + " stfd AR,AL" COM "assign double\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_VFP, + SOREG|SNAME, TDOUBLE, + SCREG, TDOUBLE, + 0, RDEST, + COM "unimplemented\n", }, + +{ ASSIGN, FOREFF|INBREG, + SOREG|SNAME, TDOUBLE, + SBREG, TDOUBLE, + 0, RDEST, + " str AR,AL" COM "assign double (soft-float)\n" + " str UR,UL\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_FPA, + SOREG|SNAME, TLDOUBLE, + SCREG, TLDOUBLE, + 0, RDEST, + " stfe AR,AL" COM "assign ldouble\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_VFP, + SOREG|SNAME, TLDOUBLE, + SCREG, TLDOUBLE, + 0, RDEST, + COM "not implemented", }, + +{ ASSIGN, FOREFF|INBREG, + SOREG|SNAME, TLDOUBLE, + SBREG, TLDOUBLE, + 0, RDEST, + " str AR,AL" COM "assign ldouble (soft-float)\n" + " str UR,UL\n", }, + +/* assign register to register */ +{ ASSIGN, FOREFF|INAREG, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + 0, RDEST, + " mov AL,AR" COM "assign AR to AL\n", }, + +{ ASSIGN, FOREFF|INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + 0, RDEST, + " mov AL,AR" COM "assign UR:AR to UL:AL\n" + " mov UL,UR\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_FPA, + SCREG, TFLOAT, + SCREG, TFLOAT, + 0, RDEST, + " mvf AL,AR" COM "assign float reg to float reg\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_VFP, + SCREG, TFLOAT, + SCREG, TFLOAT, + 0, RDEST, + " fcpys AL,AR" COM "assign float reg to float reg\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TFLOAT, + SAREG, TFLOAT, + 0, RDEST, + " mov AL,AR" COM "assign float reg to float reg\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_FPA, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + 0, RDEST, + " mvf AL,AR" COM "assign float reg to float reg\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_VFP, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + 0, RDEST, + " fcpyd AL,AR" COM "assign float reg to float reg\n", }, + +{ ASSIGN, FOREFF|INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SBREG, TDOUBLE|TLDOUBLE, + 0, RDEST, + " mov AL,AR" COM "assign (l)double reg to (l)double reg\n" + " mov UL,UR\n", }, + +{ ASSIGN, FOREFF|INAREG, + SFLD, TANY, + SOREG|SNAME, TANY, + 3*NAREG, RDEST, + " ldr A1,AR" COM "bit-field assignment\n" + " ldr A2,AL\n" + " ldr A3,=M\n" + " mov A1,A1,asl H\n" + " and A1,A1,A3\n" + " bic A2,A2,A3\n" + " orr A3,A2,A1\n" + " str A3,AL\n" + "F ldr AD,AR\n" + "FZB", }, + +{ ASSIGN, FOREFF|INAREG, + SFLD, TANY, + SAREG, TANY, + 3*NAREG, RDEST, + " ldr A2,AL" COM "bit-field assignment\n" + " ldr A3,=M\n" + " mov A1,AR,asl H\n" + " and A1,A1,A3\n" + " bic A2,A2,A3\n" + " orr A3,A2,A1\n" + " str A3,AL\n" + "F mov AD,AR\n" + "FZB", }, + +{ STASG, INAREG|FOREFF, + SOREG|SNAME, TANY, + SAREG, TPTRTO|TANY, + NSPECIAL, RRIGHT, + "ZQ", }, + +/* + * DIV/MOD/MUL + */ + +{ DIV, INAREG, + SAREG, TWORD, + SAREG, TWORD, + NSPECIAL|NAREG|NASL, RESC1, + "ZE", }, + +{ DIV, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NSPECIAL|NBREG|NBSL, RESC1, + "ZE", }, + +{ DIV, INCREG | FEATURE_FPA, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, + " dvfs A1,AL,AL" COM "fast (float) divide\n", }, + +{ DIV, INCREG | FEATURE_VFP, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, + " fdivs A1,AL,AL" COM "fast (float) divide\n", }, + +{ DIV, INAREG, + SAREG, TFLOAT, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +{ DIV, INCREG | FEATURE_FPA, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG, RESC1, + " dvfd A1,AL,AL" COM "double divide\n", }, + +{ DIV, INCREG | FEATURE_VFP, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG, RESC1, + " fdivd A1,AL,AL" COM "double divide\n", }, + +{ DIV, INBREG, + SBREG, TDOUBLE, + SBREG, TDOUBLE, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +{ DIV, INCREG | FEATURE_FPA, + SCREG, TLDOUBLE, + SCREG, TLDOUBLE, + NCREG, RESC1, + " dvfe A1,AL,AR" COM "long double load\n", }, + +{ DIV, INCREG | FEATURE_VFP, + SCREG, TLDOUBLE, + SCREG, TLDOUBLE, + NCREG, RESC1, + " fdivd A1,AL,AL" COM "double divide\n", }, + +{ DIV, INBREG, + SBREG, TLDOUBLE, + SBREG, TLDOUBLE, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +{ MOD, INAREG, + SAREG, TWORD, + SAREG, TWORD, + NSPECIAL|NAREG, RESC1, + "ZE", }, + +{ MOD, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NSPECIAL|NBREG, RESC1, + "ZE", }, + +{ MUL, INAREG | FEATURE_MUL, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG, RESC1, + " mul A1,AL,AR\n", }, + +{ MUL, INAREG, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NSPECIAL|NAREG, RESC1, + "ZE", }, + +{ MUL, INBREG | FEATURE_MULL, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + NBREG, RESC1, + " smull U1,A1,AL,AR\n", }, + +{ MUL, INBREG | FEATURE_MUL, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + NBREG, RESC1, + " mul A1,AL,AR\n" + " mov U1,A1,asr #31\n", }, + +{ MUL, INBREG, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + NSPECIAL|NBREG, RESC1, + "ZE", }, + +{ MUL, INBREG | FEATURE_MULL, + SAREG, TSWORD|TSHORT|TCHAR, + SAREG, TSWORD|TSHORT|TCHAR, + NBREG, RESC1, + " umull U1,A1,AL,AR\n", }, + +{ MUL, INBREG | FEATURE_MUL, + SAREG, TSWORD|TSHORT|TCHAR, + SAREG, TSWORD|TSHORT|TCHAR, + NBREG, RESC1, + " mul A1,AL,AR\n" + " mov U1,#0\n", }, + +{ MUL, INBREG, + SAREG, TSWORD|TSHORT|TCHAR, + SAREG, TSWORD|TSHORT|TCHAR, + NSPECIAL|NBREG, RESC1, + "ZE", }, + +{ MUL, INBREG | FEATURE_MULL, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NBREG, RESC1, + " umull U1,A1,AL,AR\n", }, + +{ MUL, INBREG | FEATURE_MUL, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NBREG, RESC1, + " mul A1,AL,AR\n" + " mov U1,A1,asr #31\n", }, + +{ MUL, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NSPECIAL|NBREG, RESC1, + "ZE", }, + +{ MUL, INCREG | FEATURE_FPA, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, + " fmls A1,AL,AL" COM "fast (float) multiply\n", }, + +{ MUL, INCREG | FEATURE_VFP, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, + " fmuls A1,AL,AL" COM "float multiply\n", }, + +{ MUL, INAREG, + SAREG, TFLOAT, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +{ MUL, INCREG | FEATURE_FPA, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + NCREG, RESC1, + " mufd A1,AL,AL" COM "fast (l)double multiply\n", }, + +{ MUL, INCREG | FEATURE_VFP, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + NCREG, RESC1, + " muld A1,AL,AL" COM "(l)double multiply\n", }, + +{ MUL, INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SBREG, TDOUBLE|TLDOUBLE, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +/* + * Indirection operators. + */ + +{ UMUL, INAREG, + SANY, TANY, + SOREG|SNAME, TWORD|TPOINT, + NAREG, RESC1, + " ldr A1,AL" COM "word load\n", }, + +{ UMUL, INAREG, + SANY, TANY, + SOREG|SNAME, TCHAR, + NAREG, RESC1, + " ldrsb A1,AL" COM "char load\n", }, + +{ UMUL, INAREG, + SANY, TANY, + SOREG|SNAME, TUCHAR, + NAREG, RESC1, + " ldrb A1,AL" COM "uchar load\n", }, + +{ UMUL, INAREG | FEATURE_HALFWORDS, + SANY, TANY, + SOREG|SNAME, TUSHORT, + NAREG, RESC1, + " ldrh A1,AL" COM "short load\n", }, + +{ UMUL, INAREG | FEATURE_HALFWORDS, + SANY, TANY, + SOREG|SNAME, TSHORT, + NAREG, RESC1, + " ldrsh A1,AL" COM "short load\n", }, + +{ UMUL, INAREG, + SANY, TANY, + SOREG|SNAME, TSHORT|TUSHORT, + 2*NAREG|NASL, RESC1, + "ZH", }, + +{ UMUL, INBREG, + SANY, TANY, + SOREG|SNAME, TLONGLONG|TULONGLONG, + NBREG, RESC1, + " ldr A1,AL" COM "64-bit load\n" + " ldr U1,UL\n", }, + +{ UMUL, INCREG | FEATURE_FPA, + SANY, TANY, + SOREG|SNAME, TFLOAT, + NCREG, RESC1, + " ldfs A1,AL" COM "float load\n", }, + +{ UMUL, INCREG | FEATURE_VFP, + SANY, TANY, + SOREG|SNAME, TFLOAT, + NCREG, RESC1, + COM "not implemented\n", }, + +{ UMUL, INAREG, + SANY, TANY, + SOREG|SNAME, TFLOAT, + NAREG, RESC1, + " ldr A1,AL" COM "float load\n", }, + +{ UMUL, INCREG | FEATURE_FPA, + SANY, TANY, + SOREG|SNAME, TDOUBLE, + NCREG, RESC1, + " ldfd A1,AL" COM "double load\n", }, + +{ UMUL, INCREG | FEATURE_VFP, + SANY, TANY, + SOREG|SNAME, TDOUBLE, + NCREG, RESC1, + COM "not implemented\n", }, + +{ UMUL, INBREG, + SANY, TANY, + SOREG|SNAME, TDOUBLE, + NBREG, RESC1, + " ldr A1,AL" COM "double load\n" + " ldr U1,UL\n", }, + +{ UMUL, INCREG | FEATURE_FPA, + SANY, TANY, + SOREG|SNAME, TLDOUBLE, + NCREG, RESC1, + " ldfe A1,AL" COM "long double load\n", }, + +{ UMUL, INCREG | FEATURE_VFP, + SANY, TANY, + SOREG|SNAME, TLDOUBLE, + NCREG, RESC1, + COM "not implemented\n", }, + +{ UMUL, INBREG, + SANY, TANY, + SOREG|SNAME, TLDOUBLE, + NBREG, RESC1, + " ldr A1,AL" COM "long double load (soft-float)\n" + " ldr U1,UL\n", }, + +/* + * Logical/branching operators + */ + +/* compare with register */ +{ OPLOG, FORCC, + SAREG, TSWORD|TSHORT|TCHAR, + SAREG, TSWORD|TSHORT|TCHAR, + 0, RESCC, + " cmp AL,AR" COM "AR-AL (sets flags)\n", }, + +/* compare with register */ +{ OPLOG, FORCC, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + 0, RESCC, + " cmp AL,AR" COM "AR-AL (sets flags)\n", }, + +/* compare with register */ +{ OPLOG, FORCC, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + 0, RESCC, + "ZD", }, + +{ OPLOG, FORCC | FEATURE_FPA, + SCREG, TFLOAT, + SCREG, TFLOAT, + NSPECIAL, RESCC, + " cmfs AL,AR" COM "float compare\n", }, + +{ OPLOG, FORCC | FEATURE_VFP, + SCREG, TFLOAT, + SCREG, TFLOAT, + 0, RESCC, + " fcmps AL,AR" COM "float compare\n", }, + +{ OPLOG, FORCC, + SAREG, TFLOAT, + SAREG, TFLOAT, + NSPECIAL, RESCC, + "ZF", }, + +{ OPLOG, FORCC | FEATURE_FPA, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NSPECIAL, RESCC, + " cmfd AL,AR" COM "double compare\n", }, + +{ OPLOG, FORCC | FEATURE_VFP, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + 0, RESCC, + " fcmpd AL,AR" COM "double compare\n", }, + +{ OPLOG, FORCC, + SBREG, TDOUBLE, + SBREG, TDOUBLE, + NSPECIAL, RESCC, + "ZF", }, + +{ OPLOG, FORCC | FEATURE_FPA, + SCREG, TLDOUBLE, + SCREG, TLDOUBLE, + NSPECIAL, RESCC, + " cmfe AL,AR" COM "ldouble compare\n", }, + +{ OPLOG, FORCC | FEATURE_VFP, + SCREG, TLDOUBLE, + SCREG, TLDOUBLE, + 0, RESCC, + " fcmpd AL,AR" COM "double compare\n", }, + +{ OPLOG, FORCC, + SBREG, TLDOUBLE, + SBREG, TLDOUBLE, + NSPECIAL, RESCC, + "ZF", }, + +/* AND/OR/ER */ +{ AND, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NBREG|NBSL, RESC1|RESCC, + " and A1,AL,AR" COM "64-bit and\n" + " and U1,UL,UR\n", }, + +{ OR, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NBREG|NBSL, RESC1, + " orr A1,AL,AR" COM "64-bit or\n" + " orr U1,UL,UR\n" }, + +{ ER, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NBREG|NBSL, RESC1, + " eor A1,AL,AR" COM "64-bit xor\n" + " eor U1,UL,UR\n" }, + +{ OPSIMP, INAREG, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1|RESCC, + " O A1,AL,AR\n", }, + +{ OPSIMP, INAREG|FORCC, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " Os A1,AL,AR\n", }, + + +/* + * Jumps. + */ +{ GOTO, FOREFF, + SCON, TANY, + SANY, TANY, + 0, RNOP, + " b LL\n", }, + +#if 0 +{ GOTO, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, RNOP, + " mov pc,AL\n", }, +#endif + +/* + * Convert LTYPE to reg. + */ + +{ OPLTYPE, INAREG, + SANY, TANY, + SOREG|SNAME, TWORD|TPOINT, + NAREG, RESC1, + " ldr A1,AL" COM "load word from memory\n", }, + +{ OPLTYPE, INBREG, + SANY, TANY, + SOREG|SNAME, TLONGLONG|TULONGLONG, + NBREG, RESC1, + " ldr A1,AL" COM "load long long from memory\n" + " ldr U1,UL\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SOREG|SNAME, TCHAR, + NAREG, RESC1, + " ldrsb A1,AL" COM "load char from memory\n" }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SOREG|SNAME, TUCHAR, + NAREG, RESC1, + " ldrb A1,AL" COM "load uchar from memory\n", }, + +{ OPLTYPE, INAREG | FEATURE_HALFWORDS, + SANY, TANY, + SOREG|SNAME, TSHORT, + NAREG, RESC1, + " ldrsh A1,AL" COM "load short from memory\n", }, + +{ OPLTYPE, INAREG | FEATURE_HALFWORDS, + SANY, TANY, + SOREG|SNAME, TUSHORT, + NAREG, RESC1, + " ldrh A1,AL" COM "load ushort from memory\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SOREG|SNAME, TSHORT|TUSHORT, + 2*NAREG, RESC1, + "ZH", }, + +#if 0 +{ OPLTYPE, INAREG, + SANY, TANY, + SCON, TPOINT, + NAREG, RESC1, + " ldr A1,AL" COM "load integer constant\n", }, +#endif + +{ OPLTYPE, INAREG, + SANY, TANY, + SCON, TANY, + NAREG, RESC1, + "ZI", }, + +{ OPLTYPE, INBREG, + SANY, TANY, + SCON, TANY, + NBREG, RESC1, + "ZJ", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SAREG, TANY, + NAREG, RESC1, + " mov A1,AL" COM "load AL into A1\n" }, + +{ OPLTYPE, INBREG, + SANY, TANY, + SBREG, TLONGLONG|TULONGLONG, + NBREG, RESC1, + " mov A1,AL" COM "load UL:AL into U1:A1\n" + " mov U1,UL\n", }, + +{ OPLTYPE, INCREG | FEATURE_FPA, + SANY, TANY, + SOREG|SNAME, TFLOAT, + NCREG, RESC1, + " ldfs A1,AL" COM "load float\n", }, + +{ OPLTYPE, INCREG | FEATURE_VFP, + SANY, TANY, + SOREG|SNAME, TFLOAT, + NCREG, RESC1, + COM "not implemented\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SOREG|SNAME, TFLOAT, + NAREG, RESC1, + " ldr A1,AL" COM "load float (soft-float)\n", }, + +{ OPLTYPE, INCREG | FEATURE_FPA, + SANY, TANY, + SOREG|SNAME, TDOUBLE, + NCREG, RESC1, + " ldfd A1,AL" COM "load double\n", }, + +{ OPLTYPE, INCREG | FEATURE_VFP, + SANY, TANY, + SOREG|SNAME, TDOUBLE, + NCREG, RESC1, + COM "not implemented\n" }, + +{ OPLTYPE, INBREG, + SANY, TANY, + SOREG|SNAME, TDOUBLE, + NBREG, RESC1, + " ldr A1,AL" COM "load double (soft-float)\n" + " ldr U1,UL\n", }, + +{ OPLTYPE, INCREG | FEATURE_FPA, + SANY, TANY, + SOREG|SNAME, TLDOUBLE, + NCREG, RESC1, + " ldfe A1,AL" COM "load ldouble\n", }, + +{ OPLTYPE, INCREG | FEATURE_VFP, + SANY, TANY, + SOREG|SNAME, TLDOUBLE, + NCREG, RESC1, + COM "not implemented\n", }, + +{ OPLTYPE, INBREG, + SANY, TANY, + SOREG|SNAME, TLDOUBLE, + NBREG, RESC1, + " ldr A1,AL" COM "load ldouble (soft-float)\n" + " ldr U1,UL\n", }, + +/* + * Negate a word. + */ + +{ UMINUS, INAREG, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " rsb A1,AL,#0" COM "negation\n", }, + +{ UMINUS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NBREG|NBSL, RESC1, + " rsbs A1,AL,#0" COM "64-bit negation\n" + " rsc U1,UL,#0\n", }, + +{ UMINUS, INCREG | FEATURE_FPA, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, + " mvfs A1,AL" COM "float negation\n", }, + +{ UMINUS, INCREG | FEATURE_VFP, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, + " negs A1,AL" COM "float negation\n", }, + +{ UMINUS, INAREG, + SAREG, TFLOAT, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +{ UMINUS, INCREG | FEATURE_FPA, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG, RESC1, + " mvfd A1,AL" COM "double negation\n", }, + +{ UMINUS, INCREG | FEATURE_VFP, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG, RESC1, + " negd A1,AL" COM "double negation\n", }, + +{ UMINUS, INBREG, + SBREG, TDOUBLE, + SBREG, TDOUBLE, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +{ UMINUS, INCREG | FEATURE_FPA, + SCREG, TLDOUBLE, + SCREG, TLDOUBLE, + NCREG, RESC1, + " mvfe A1,AL" COM "ldouble negation\n", }, + +{ UMINUS, INCREG | FEATURE_VFP, + SCREG, TLDOUBLE, + SCREG, TLDOUBLE, + NCREG, RESC1, + " negd A1,AL" COM "ldouble negation\n", }, + +{ UMINUS, INBREG, + SBREG, TLDOUBLE, + SBREG, TLDOUBLE, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +{ COMPL, INAREG, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SANY, TANY, + NAREG|NASL, RESC1, + " mvn A1,AL" COM "complement\n", }, + +{ COMPL, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SANY, TANY, + NBREG|NBSL, RESC1, + " mvn A1,AL" COM "64-bit complement\n" + " mvn U1,UL\n", }, + +/* + * Arguments to functions. + */ + +{ FUNARG, FOREFF, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SANY, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + 0, 0, + " stmfd sp!,{AL}" COM "save function arg to stack\n", }, + +{ FUNARG, FOREFF, + SBREG, TLONGLONG|TULONGLONG, + SANY, TLONGLONG|TULONGLONG, + 0, 0, + " stmfd sp!,{AL,UL}" COM "save function arg to stack (endianness problem here?)\n", }, + +{ FUNARG, FOREFF, + SCREG, TFLOAT, + SANY, TFLOAT, + 0, 0, + " stmfd sp!,{AL}" COM "save function arg to stack\n", }, + +{ FUNARG, FOREFF, + SCREG, TDOUBLE|TLDOUBLE, + SANY, TDOUBLE|TLDOUBLE, + 0, 0, + " stmfd sp!,{AL,UL}" COM "save function arg to stack (endianness problem here?)\n", }, + +# define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,"" + +{ UMUL, DF( UMUL ), }, + +{ ASSIGN, DF(ASSIGN), }, + +{ STASG, DF(STASG), }, + +{ FLD, DF(FLD), }, + +{ OPLEAF, DF(NAME), }, + +/* { INIT, DF(INIT), }, */ + +{ OPUNARY, DF(UMINUS), }, + +{ OPANY, DF(BITYPE), }, + +{ FREE, FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" }, +}; + +int tablesize = sizeof(table)/sizeof(table[0]); diff --git a/compilers/pcc/pcc-1.0.0/arch/hppa/CVS/Entries b/compilers/pcc/pcc-1.0.0/arch/hppa/CVS/Entries new file mode 100644 index 00000000..8137084c --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/hppa/CVS/Entries @@ -0,0 +1,7 @@ +/code.c/1.22/Sun Feb 8 16:12:40 2009//Tr-1-0-0-RELEASE +/local.c/1.28/Fri Jan 21 21:47:58 2011//Tr-1-0-0-RELEASE +/local2.c/1.29/Mon Sep 7 10:15:03 2009//Tr-1-0-0-RELEASE +/macdefs.h/1.15/Thu Sep 10 21:52:37 2009//Tr-1-0-0-RELEASE +/order.c/1.9/Sat Sep 27 07:35:22 2008//Tr-1-0-0-RELEASE +/table.c/1.14/Sat Nov 22 23:31:01 2008//Tr-1-0-0-RELEASE +D diff --git a/compilers/pcc/pcc-1.0.0/arch/hppa/CVS/Repository b/compilers/pcc/pcc-1.0.0/arch/hppa/CVS/Repository new file mode 100644 index 00000000..7edf4453 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/hppa/CVS/Repository @@ -0,0 +1 @@ +pcc/arch/hppa diff --git a/compilers/pcc/pcc-1.0.0/arch/hppa/CVS/Root b/compilers/pcc/pcc-1.0.0/arch/hppa/CVS/Root new file mode 100644 index 00000000..71e2ccb9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/hppa/CVS/Root @@ -0,0 +1 @@ +/cvsroot diff --git a/compilers/pcc/pcc-1.0.0/arch/hppa/CVS/Tag b/compilers/pcc/pcc-1.0.0/arch/hppa/CVS/Tag new file mode 100644 index 00000000..060fac05 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/hppa/CVS/Tag @@ -0,0 +1 @@ +Nr-1-0-0-RELEASE diff --git a/compilers/pcc/pcc-1.0.0/arch/hppa/code.c b/compilers/pcc/pcc-1.0.0/arch/hppa/code.c new file mode 100644 index 00000000..8c681039 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/hppa/code.c @@ -0,0 +1,277 @@ +/* $OpenBSD: code.c,v 1.2 2007/11/22 15:06:43 stefan Exp $ */ + +/* + * Copyright (c) 2007 Michael Shalayeff + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass1.h" + +NODE *funarg(NODE *, int *); +int argreg(TWORD, int *); + +static const char *const loctbl[] = { "text", "data", "section .rodata" }; + +/* + * Define everything needed to print out some data (or text). + * This means segment, alignment, visibility, etc. + */ +void +defloc(struct symtab *sp) +{ + extern char *nextsect; + static int lastloc = -1; + TWORD t; + char *n; + int s; + + if (sp == NULL) { + lastloc = -1; + return; + } + t = sp->stype; + s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA; + if (nextsect) { + printf("\t.section %s\n", nextsect); + nextsect = NULL; + s = -1; + } else if (s != lastloc) + printf("\t.%s\n", loctbl[s]); + lastloc = s; + while (ISARY(t)) + t = DECREF(t); + s = ISFTN(t) ? ALINT : talign(t, sp->ssue); + if (s > ALCHAR) + printf("\t.align\t%d\n", s / ALCHAR); + n = sp->soname ? sp->soname : sp->sname; + if (sp->sclass == EXTDEF) + printf("\t.export %s, %s\n", n, + ISFTN(t)? "code" : "data"); + if (sp->slevel == 0) + printf("\t.type\t%s, @%s\n\t.label %s\n", + n, ISFTN(t)? "function" : "object", n); + else + printf("\t.type\t" LABFMT ", @%s\n\t.label\t" LABFMT "\n", + sp->soffset, ISFTN(t)? "function" : "object", sp->soffset); +} + +/* + * code for the end of a function + * deals with struct return here + */ +void +efcode() +{ + NODE *p, *q; + int sz; + + if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) + return; + /* address of return struct is in %ret0 */ + /* create a call to memcpy() */ + /* will get the result in %ret0 */ + p = block(REG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR)); + p->n_rval = RET0; + q = block(OREG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR)); + q->n_rval = FP; + q->n_lval = 8; /* return buffer offset */ + p = block(CM, q, p, INT, 0, MKSUE(INT)); + sz = (tsize(STRTY, cftnsp->sdf, cftnsp->ssue)+SZCHAR-1)/SZCHAR; + p = block(CM, p, bcon(sz), INT, 0, MKSUE(INT)); + p->n_right->n_name = ""; + p = block(CALL, bcon(0), p, CHAR+PTR, 0, MKSUE(CHAR+PTR)); + p->n_left->n_name = "memcpy"; + p = clocal(p); + send_passt(IP_NODE, p); +} + +int +argreg(TWORD t, int *n) +{ + switch (t) { + case FLOAT: + return FR7L - 2 * (*n)++; + case DOUBLE: + case LDOUBLE: + *n += 2; + return FR6 - *n - 2; + case LONGLONG: + case ULONGLONG: + *n += 2; + return AD1 - (*n - 2) / 2; + default: + return ARG0 - (*n)++; + } +} + +/* + * code for the beginning of a function; 'a' is an array of + * indices in symtab for the arguments; n is the number + */ +void +bfcode(struct symtab **a, int cnt) +{ + struct symtab *sp; + NODE *p, *q; + int i, n, sz; + + if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) { + /* Function returns struct, adjust arg offset */ + for (i = 0; i < n; i++) + a[i]->soffset += SZPOINT(LONG); + } + + /* recalculate the arg offset and create TEMP moves */ + for (n = 0, i = 0; i < cnt; i++) { + sp = a[i]; + + sz = szty(sp->stype); + if (n % sz) + n++; /* XXX LDOUBLE */ + + if (n < 4) { + p = tempnode(0, sp->stype, sp->sdf, sp->ssue); + /* TODO p->n_left->n_lval = -(32 + n * 4); */ + q = block(REG, NIL, NIL, sp->stype, sp->sdf, sp->ssue); + q->n_rval = argreg(sp->stype, &n); + p = buildtree(ASSIGN, p, q); + sp->soffset = regno(p->n_left); + sp->sflags |= STNODE; + ecomp(p); + } else { + sp->soffset += SZINT * n; + if (xtemps) { + /* put stack args in temps if optimizing */ + p = tempnode(0, sp->stype, sp->sdf, sp->ssue); + p = buildtree(ASSIGN, p, buildtree(NAME, 0, 0)); + sp->soffset = regno(p->n_left); + sp->sflags |= STNODE; + ecomp(p); + } + } + } +} + + +/* + * by now, the automatics and register variables are allocated + */ +void +bccode() +{ + SETOFF(autooff, SZINT); +} + +/* called just before final exit */ +/* flag is 1 if errors, 0 if none */ +void +ejobcode(int errors) +{ + if (errors) + return; + + printf("\t.end\n"); +} + +void +bjobcode(void) +{ + printf("\t.level\t1.1\n" + "\t.import $global$, data\n" + "\t.import $$dyncall, millicode\n"); +} + +/* + * return the alignment of field of type t + */ +int +fldal(unsigned int t) +{ + uerror("illegal field type"); + return(ALINT); +} + +/* fix up type of field p */ +void +fldty(struct symtab *p) +{ +} + +/* + * XXX - fix genswitch. + */ +int +mygenswitch(int num, TWORD type, struct swents **p, int n) +{ + return 0; +} + +NODE * +funarg(NODE *p, int *n) +{ + NODE *r; + int sz; + + if (p->n_op == CM) { + p->n_left = funarg(p->n_left, n); + p->n_right = funarg(p->n_right, n); + return p; + } + + sz = szty(p->n_type); + if (*n % sz) + (*n)++; /* XXX LDOUBLE */ + + if (*n >= 4) { + *n += sz; + r = block(OREG, NIL, NIL, p->n_type|PTR, 0, + MKSUE(p->n_type|PTR)); + r->n_rval = SP; + r->n_lval = -(32 + *n * 4); + } else { + r = block(REG, NIL, NIL, p->n_type, 0, 0); + r->n_lval = 0; + r->n_rval = argreg(p->n_type, n); + } + p = block(ASSIGN, r, p, p->n_type, 0, 0); + clocal(p); + + return p; +} + +/* + * Called with a function call with arguments as argument. + * This is done early in buildtree() and only done once. + */ +NODE * +funcode(NODE *p) +{ + int n = 0; + + p->n_right = funarg(p->n_right, &n); + return p; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/hppa/local.c b/compilers/pcc/pcc-1.0.0/arch/hppa/local.c new file mode 100644 index 00000000..98f86d0c --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/hppa/local.c @@ -0,0 +1,994 @@ +/* $OpenBSD: local.c,v 1.2 2007/11/18 17:39:55 ragge Exp $ */ + +/* + * Copyright (c) 2007 Michael Shalayeff + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "pass1.h" +#include "pass2.h" + +/* this file contains code which is dependent on the target machine */ + +#define IALLOC(sz) (isinlining ? permalloc(sz) : tmpalloc(sz)) + +struct symtab *makememcpy(void); +char *section2string(char *, int); + +/* clocal() is called to do local transformations on + * an expression tree preparitory to its being + * written out in intermediate code. + * + * the major essential job is rewriting the + * automatic variables and arguments in terms of + * REG and OREG nodes + * conversion ops which are not necessary are also clobbered here + * in addition, any special features (such as rewriting + * exclusive or) are easily handled here as well + */ +NODE * +clocal(NODE *p) +{ + register struct symtab *q, *sp; + register NODE *r, *l, *s; + register int o, m, rn; + char *ch, name[16], *n; + TWORD t; + +#ifdef PCC_DEBUG + if (xdebug) { + printf("clocal: %p\n", p); + fwalk(p, eprint, 0); + } +#endif + switch (o = p->n_op) { + + case NAME: + if ((q = p->n_sp) == NULL) + break; /* Nothing to care about */ + + switch (q->sclass) { + + case PARAM: + /* first four integral args are in regs */ + rn = (q->soffset >> 5) - 8; + if (rn < 4) { + r = block(REG, NIL, NIL, p->n_type, 0, 0); + r->n_lval = 0; + switch (p->n_type) { + case FLOAT: + r->n_rval = FR7L - rn; + break; + case DOUBLE: + case LDOUBLE: + r->n_rval = FR6 - rn; + break; + case LONGLONG: + case ULONGLONG: + r->n_rval = AD1 - rn / 2; + break; + default: + r->n_rval = ARG0 - rn; + } + r->n_sue = p->n_sue; + p->n_sue = NULL; + nfree(p); + p = r; + break; + } + /* FALLTHROUGH */ + + case AUTO: + /* fake up a structure reference */ + r = block(REG, NIL, NIL, PTR+STRTY, 0, 0); + r->n_lval = 0; + r->n_rval = FPREG; + p = stref(block(STREF, r, p, 0, 0, 0)); + break; + + case REGISTER: + p->n_op = REG; + p->n_lval = 0; + p->n_rval = q->soffset; + break; + + case STATIC: + case EXTERN: + if (p->n_sp->sflags & SSTRING) + break; + + n = p->n_sp->soname ? p->n_sp->soname : p->n_sp->sname; + if (strncmp(n, "__builtin", 9) == 0) + break; + + l = block(REG, NIL, NIL, INT, 0, 0); + l->n_lval = 0; + l->n_rval = R1; + l = block(ASSIGN, l, p, INT, 0, 0); + r = xbcon(0, p->n_sp, INT); + p = block(UMUL, + block(PLUS, l, r, INT, 0, 0), + NIL, p->n_type, p->n_df, p->n_sue); + break; + } + break; + + case ADDROF: + l = p->n_left; + if (!l->n_sp) + break; + + if (l->n_sp->sclass != EXTERN && + l->n_sp->sclass != STATIC && + l->n_sp->sclass != USTATIC && + l->n_sp->sclass != EXTDEF) + break; + + l = block(REG, NIL, NIL, INT, 0, 0); + l->n_lval = 0; + l->n_rval = R1; + l = block(ASSIGN, l, p->n_left, INT, 0, 0); + r = xbcon(0, p->n_left->n_sp, INT); + l = block(PLUS, l, r, p->n_type, p->n_df, p->n_sue); + nfree(p); + p = l; + break; + + case CBRANCH: + l = p->n_left; + + /* + * Remove unnecessary conversion ops. + */ + if (clogop(l->n_op) && l->n_left->n_op == SCONV) { + if (coptype(l->n_op) != BITYPE) + break; + if (l->n_right->n_op == ICON) { + r = l->n_left->n_left; + if (r->n_type >= FLOAT && r->n_type <= LDOUBLE) + break; + /* Type must be correct */ + t = r->n_type; + nfree(l->n_left); + l->n_left = r; + l->n_type = t; + l->n_right->n_type = t; + } + } + break; + + case PCONV: + /* Remove redundant PCONV's. Be careful */ + l = p->n_left; + if (l->n_op == ICON) { + l->n_lval = (unsigned)l->n_lval; + goto delp; + } + if (l->n_type < INT || l->n_type == LONGLONG || + l->n_type == ULONGLONG) { + /* float etc? */ + p->n_left = block(SCONV, l, NIL, + UNSIGNED, 0, MKSUE(UNSIGNED)); + break; + } + /* if left is SCONV, cannot remove */ + if (l->n_op == SCONV) + break; + + /* avoid ADDROF TEMP */ + if (l->n_op == ADDROF && l->n_left->n_op == TEMP) + break; + + /* if conversion to another pointer type, just remove */ + if (p->n_type > BTMASK && l->n_type > BTMASK) + goto delp; + break; + + delp: l->n_type = p->n_type; + l->n_qual = p->n_qual; + l->n_df = p->n_df; + l->n_sue = p->n_sue; + nfree(p); + p = l; + break; + + case SCONV: + l = p->n_left; + + if (p->n_type == l->n_type) { + nfree(p); + p = l; + break; + } + + if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 && + btdims[p->n_type].suesize == btdims[l->n_type].suesize) { + if (p->n_type != FLOAT && p->n_type != DOUBLE && + l->n_type != FLOAT && l->n_type != DOUBLE && + l->n_type != LDOUBLE && p->n_type != LDOUBLE) { + if (l->n_op == UMUL || l->n_op == TEMP || + l->n_op == NAME) { + l->n_type = p->n_type; + nfree(p); + p = l; + break; + } + } + } + + if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT && + coptype(l->n_op) == BITYPE) { + l->n_type = p->n_type; + nfree(p); + p = l; + break; + } + + o = l->n_op; + m = p->n_type; + + if (o == ICON) { + CONSZ val = l->n_lval; + + if (!ISPTR(m)) /* Pointers don't need to be conv'd */ + switch (m) { + case BOOL: + l->n_lval = l->n_lval != 0; + break; + case CHAR: + l->n_lval = (char)val; + break; + case UCHAR: + l->n_lval = val & 0377; + break; + case SHORT: + l->n_lval = (short)val; + break; + case USHORT: + l->n_lval = val & 0177777; + break; + case ULONG: + case UNSIGNED: + l->n_lval = val & 0xffffffff; + break; + case LONG: + case INT: + l->n_lval = (int)val; + break; + case LONGLONG: + l->n_lval = (long long)val; + break; + case ULONGLONG: + l->n_lval = val; + break; + case VOID: + break; + case LDOUBLE: + case DOUBLE: + case FLOAT: + l->n_op = FCON; + l->n_dcon = val; + break; + default: + cerror("unknown type %d", m); + } + l->n_type = m; + l->n_sue = MKSUE(m); + nfree(p); + return l; + } else if (l->n_op == FCON) { + l->n_lval = l->n_dcon; + l->n_sp = NULL; + l->n_op = ICON; + l->n_type = m; + l->n_sue = MKSUE(m); + nfree(p); + return clocal(l); + } + + if (DEUNSIGN(p->n_type) == SHORT && + DEUNSIGN(l->n_type) == SHORT) { + nfree(p); + p = l; + } + if ((p->n_type == CHAR || p->n_type == UCHAR || + p->n_type == SHORT || p->n_type == USHORT) && + (l->n_type == FLOAT || l->n_type == DOUBLE || + l->n_type == LDOUBLE)) { + p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_sue); + p->n_left->n_type = INT; + break; + } + break; + + case MOD: + case DIV: + if (o == DIV && p->n_type != CHAR && p->n_type != SHORT) + break; + if (o == MOD && p->n_type != CHAR && p->n_type != SHORT) + break; + /* make it an int division by inserting conversions */ + p->n_left = block(SCONV, p->n_left, NIL, INT, 0, MKSUE(INT)); + p->n_right = block(SCONV, p->n_right, NIL, INT, 0, MKSUE(INT)); + p = block(SCONV, p, NIL, p->n_type, 0, MKSUE(p->n_type)); + p->n_left->n_type = INT; + break; + + case PMCONV: + case PVCONV: + if( p->n_right->n_op != ICON ) cerror( "bad conversion", 0); + nfree(p); + return(buildtree(o==PMCONV?MUL:DIV, p->n_left, p->n_right)); + + case LS: + case RS: + /* shift count must be in an int */ + if (p->n_right->n_op == ICON || p->n_right->n_lval <= 32) + break; /* do not do anything */ + if (p->n_right->n_type != INT || p->n_right->n_lval > 32) + p->n_right = block(SCONV, p->n_right, NIL, + INT, 0, MKSUE(INT)); + break; + +#if 0 + case FLD: + /* already rewritten (in ASSIGN) */ + if (p->n_left->n_op == TEMP) + break; + + r = tempnode(0, p->n_type, p->n_df, p->n_sue); + l = block(ASSIGN, r, p->n_left, p->n_type, p->n_df, p->n_sue); + p->n_left = tcopy(r); + p = block(COMOP, l, p, p->n_type, p->n_df, p->n_sue); + break; +#endif + + case FORCE: + /* put return value in return reg */ + p->n_op = ASSIGN; + p->n_right = p->n_left; + p->n_left = block(REG, NIL, NIL, p->n_type, p->n_df, p->n_sue); + p->n_left->n_rval = p->n_left->n_type == BOOL ? + RETREG(CHAR) : RETREG(p->n_type); + if (p->n_right->n_op != FLD) + break; + break; + + case ASSIGN: + r = p->n_right; + l = p->n_left; + + /* rewrite ICON#0 into %r0 */ + if (r->n_op == ICON && r->n_lval == 0 && + (l->n_op == REG || l->n_op == OREG)) { + r->n_op = REG; + r->n_rval = R0; + } + + /* rewrite FCON#0 into %fr0 */ + if (r->n_op == FCON && r->n_lval == 0 && l->n_op == REG) { + r->n_op = REG; + r->n_rval = r->n_type == FLOAT? FR0L : FR0; + } + + if (p->n_left->n_op != FLD) + break; + + r = tempnode(0, l->n_type, l->n_df, l->n_sue); + p = block(COMOP, + block(ASSIGN, r, l->n_left, l->n_type, l->n_df, l->n_sue), + p, p->n_type, p->n_df, p->n_sue); + s = tcopy(l->n_left); + p = block(COMOP, p, + block(ASSIGN, s, tcopy(r), l->n_type, l->n_df, l->n_sue), + p->n_type, p->n_df, p->n_sue); + l->n_left = tcopy(r); + break; + + case STASG: + /* memcpy(left, right, size) */ + sp = makememcpy(); + l = p->n_left; + /* guess struct return */ + if (l->n_op == NAME && ISFTN(l->n_sp->stype)) { + l = block(REG, NIL, NIL, VOID|PTR, 0, MKSUE(LONG)); + l->n_lval = 0; + l->n_rval = RET0; + } else if (l->n_op == UMUL) + l = tcopy(l->n_left); + else if (l->n_op == NAME) + l = block(ADDROF,tcopy(l),NIL,PTR|STRTY,0,MKSUE(LONG)); + l = block(CALL, block(ADDROF, + (s = block(NAME, NIL, NIL, FTN, 0, MKSUE(LONG))), + NIL, PTR|FTN, 0, MKSUE(LONG)), + block(CM, block(CM, l, tcopy(p->n_right), + STRTY|PTR, 0, MKSUE(LONG)), + (r = block(ICON, NIL, NIL, INT, 0, MKSUE(LONG))), 0, 0, 0), + INT, 0, MKSUE(LONG)); + r->n_lval = p->n_sue->suesize/SZCHAR; + s->n_sp = sp; + s->n_df = s->n_sp->sdf; + defid(s, EXTERN); + tfree(p); + p = l; + p->n_left = clocal(p->n_left); + p->n_right = clocal(p->n_right); + calldec(p->n_left, p->n_right); + funcode(p); + break; + + case STARG: + /* arg = memcpy(argN-size, src, size) */ + sp = makememcpy(); + l = block(CALL, block(ADDROF, + (s = block(NAME, NIL, NIL, FTN, 0, MKSUE(LONG))),NIL,0,0,0), + block(CM, block(CM, tcopy(p), tcopy(p->n_left), 0, 0, 0), + (r = block(ICON, NIL, NIL, INT, 0, MKSUE(LONG))), 0, 0, 0), + INT, 0, MKSUE(LONG)); + r->n_lval = p->n_sue->suesize/SZCHAR; + s->n_sp = sp; + s->n_df = s->n_sp->sdf; + defid(s, EXTERN); + tfree(p); + p = l; + p->n_left = clocal(p->n_left); + calldec(p->n_left, p->n_right); + funcode(p); + break; + + case STCALL: + case CALL: + for (r = p->n_right; r->n_op == CM; r = r->n_left) { + if (r->n_right->n_op == ASSIGN && + r->n_right->n_right->n_op == CALL) { + s = r->n_right->n_right; + l = tempnode(0, s->n_type, s->n_df, s->n_sue); + ecode(buildtree(ASSIGN, l, s)); + r->n_right->n_right = tcopy(l); + } + if (r->n_left->n_op == ASSIGN && + r->n_left->n_right->n_op == CALL) { + s = r->n_left->n_right; + l = tempnode(0, s->n_type, s->n_df, s->n_sue); + ecode(buildtree(ASSIGN, l, s)); + r->n_left->n_right = tcopy(l); + } + } + break; + } + + /* second pass - rewrite long ops */ + switch (o) { + case DIV: + case MOD: + case MUL: + case RS: + case LS: + if (!(p->n_type == LONGLONG || p->n_type == ULONGLONG) || + !((o == DIV || o == MOD || o == MUL) && + p->n_type < FLOAT)) + break; + if (o == DIV && p->n_type == ULONGLONG) ch = "udiv"; + else if (o == DIV) ch = "div"; + else if (o == MUL) ch = "mul"; + else if (o == MOD && p->n_type == ULONGLONG) ch = "umod"; + else if (o == MOD) ch = "mod"; + else if (o == RS && p->n_type == ULONGLONG) ch = "lshr"; + else if (o == RS) ch = "ashr"; + else if (o == LS) ch = "ashl"; + else break; + snprintf(name, sizeof(name), "__%sdi3", ch); + p->n_right = block(CM, p->n_left, p->n_right, 0, 0, 0); + p->n_left = block(ADDROF, + block(NAME, NIL, NIL, FTN, 0, MKSUE(INT)), NIL, + PTR|FTN, 0, MKSUE(INT)); + p->n_left->n_left->n_sp = lookup(addname(name), 0); + defid(p->n_left->n_left, EXTERN); + p->n_left = clocal(p->n_left); + calldec(p->n_left, p->n_right); + p->n_op = CALL; + funcode(p); + break; + } + +#ifdef PCC_DEBUG + if (xdebug) { + printf("clocal end: %p\n", p); + fwalk(p, eprint, 0); + } +#endif + return(p); +} + +struct symtab * +makememcpy() +{ + NODE *memcpy, *args, *t, *u; + struct symtab *sp; + + /* TODO check that it's a func proto */ + if ((sp = lookup(addname("memcpy"), SNORMAL))) + return sp; + + memcpy = block(NAME, NIL, NIL, 0, 0, MKSUE(LONG)); + memcpy->n_sp = sp = lookup(addname("memcpy"), SNORMAL); + defid(memcpy, EXTERN); + + args = block(CM, block(CM, + block(NAME, NIL, NIL, VOID|PTR, 0, MKSUE(LONG)), + block(NAME, NIL, NIL, VOID|PTR, 0, MKSUE(LONG)), 0, 0, 0), + block(NAME, NIL, NIL, LONG, 0, MKSUE(LONG)), 0, 0, 0); + + tymerge(t = block(TYPE, NIL, NIL, VOID|PTR, 0, 0), + (u = block(UMUL, block(CALL, memcpy, args, LONG, 0, 0), + NIL, LONG, 0, 0))); + tfree(t); + tfree(u); + + return sp; +} + +void +myp2tree(NODE *p) +{ + struct symtab *sp; + int o = p->n_op; + + if (o != FCON) + return; + + /* Write float constants to memory */ + /* Should be volontary per architecture */ + +#if 0 + setloc1(RDATA); + defalign(p->n_type == FLOAT ? ALFLOAT : p->n_type == DOUBLE ? + ALDOUBLE : ALLDOUBLE ); + deflab1(i = getlab()); +#endif + sp = inlalloc(sizeof(struct symtab)); + sp->sclass = STATIC; + sp->ssue = MKSUE(p->n_type); + sp->slevel = 1; /* fake numeric label */ + sp->soffset = getlab(); + sp->sflags = 0; + sp->stype = p->n_type; + sp->squal = (CON >> TSHIFT); + + defloc(sp); + ninval(0, btdims[p->n_type].suesize, p); + + p->n_op = NAME; + p->n_lval = 0; + p->n_sp = sp; + +} + +/*ARGSUSED*/ +int +andable(NODE *p) +{ + return(1); /* all names can have & taken on them */ +} + +/* + * at the end of the arguments of a ftn, set the automatic offset + */ +void +cendarg() +{ + /* TODO can use to generate sp/rp tree ops? */ + autooff = AUTOINIT; +} + +/* + * Return 1 if a variable of type "t" is OK to put in register. + */ +int +cisreg(TWORD t) +{ + return 1; +} + +/* + * return a node, for structure references, which is suitable for + * being added to a pointer of type t, in order to be off bits offset + * into a structure + * t, d, and s are the type, dimension offset, and sizeoffset + * For pdp10, return the type-specific index number which calculation + * is based on its size. For example, short a[3] would return 3. + * Be careful about only handling first-level pointers, the following + * indirections must be fullword. + */ +NODE * +offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue) +{ + register NODE *p; + + if (xdebug) + printf("offcon: OFFSZ %lld type %x dim %p siz %d\n", + off, t, d, sue->suesize); + + p = bcon(0); + p->n_lval = off/SZCHAR; /* Default */ + return(p); +} + +/* + * Allocate off bits on the stack. p is a tree that when evaluated + * is the multiply count for off, t is a storeable node where to write + * the allocated address. + */ +void +spalloc(NODE *t, NODE *p, OFFSZ off) +{ + NODE *sp; + + p = buildtree(MUL, p, bcon(off/SZCHAR)); /* XXX word alignment? */ + + /* sub the size from sp */ + sp = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT)); + sp->n_lval = 0; + sp->n_rval = STKREG; + ecomp(buildtree(PLUSEQ, sp, p)); + + /* save the address of sp */ + sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_sue); + sp->n_lval = 0; + sp->n_rval = STKREG; + t->n_type = sp->n_type; + ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */ + +} + +#if 0 +/* + * Print out an integer constant of size size. + * can only be sizes <= SZINT. + */ +void +indata(CONSZ val, int size) +{ + switch (size) { + case SZCHAR: + printf("\t.byte %d\n", (int)val & 0xff); + break; + case SZSHORT: + printf("\t.word %d\n", (int)val & 0xffff); + break; + case SZINT: + printf("\t.long %d\n", (int)val & 0xffffffff); + break; + default: + cerror("indata"); + } +} +#endif + +/* + * Print out a string of characters. + * Assume that the assembler understands C-style escape + * sequences. Location is already set. + */ +void +instring(struct symtab *sp) +{ + char *s, *str; + + defloc(sp); + str = sp->sname; + + /* be kind to assemblers and avoid long strings */ + printf("\t.ascii\t\""); + for (s = str; *s != 0; ) { + if (*s++ == '\\') { + (void)esccon(&s); + } + if (s - str > 64) { + fwrite(str, 1, s - str, stdout); + printf("\"\n\t.ascii\t\""); + str = s; + } + } + fwrite(str, 1, s - str, stdout); + printf("\\0\"\n"); +} + +static int inbits, inval; + +/* + * set fsz bits in sequence to zero. + */ +void +zbits(OFFSZ off, int fsz) +{ + int m; + + if (idebug) + printf("zbits off %lld, fsz %d inbits %d\n", off, fsz, inbits); + if ((m = (inbits % SZCHAR))) { + m = SZCHAR - m; + if (fsz < m) { + inbits += fsz; + return; + } else { + fsz -= m; + printf("\t.byte %d\n", inval); + inval = inbits = 0; + } + } + if (fsz >= SZCHAR) { + printf("\t.zero %d\n", fsz/SZCHAR); + fsz -= (fsz/SZCHAR) * SZCHAR; + } + if (fsz) { + inval = 0; + inbits = fsz; + } +} + +/* + * Initialize a bitfield. + */ +void +infld(CONSZ off, int fsz, CONSZ val) +{ + if (idebug) + printf("infld off %lld, fsz %d, val %lld inbits %d\n", + off, fsz, val, inbits); + val &= (1 << fsz)-1; + while (fsz + inbits >= SZCHAR) { + inval |= (val << inbits); + printf("\t.byte %d\n", inval & 255); + fsz -= (SZCHAR - inbits); + val >>= (SZCHAR - inbits); + inval = inbits = 0; + } + if (fsz) { + inval |= (val << inbits); + inbits += fsz; + } +} + +/* + * print out a constant node, may be associated with a label. + * Do not free the node after use. + * off is bit offset from the beginning of the aggregate + * fsz is the number of bits this is referring to + * + * XXX this relies on the host fp numbers representation + */ +void +ninval(CONSZ off, int fsz, NODE *p) +{ + union { float f; double d; long double l; int i[3]; } u; + struct symtab *q; + TWORD t; + int i; + + t = p->n_type; + if (t > BTMASK) + t = INT; /* pointer */ + + if (p->n_op != ICON && p->n_op != FCON) + cerror("ninval: init node not constant"); + + if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT) + uerror("element not constant"); + + switch (t) { + case LONGLONG: + case ULONGLONG: + i = (p->n_lval >> 32); + p->n_lval &= 0xffffffff; + p->n_type = INT; + ninval(off, 32, p); + p->n_lval = i; + ninval(off+32, 32, p); + break; + case INT: + case UNSIGNED: + printf("\t.long 0x%x", (int)p->n_lval); + if ((q = p->n_sp) != NULL) { + if ((q->sclass == STATIC && q->slevel > 0)) { + printf("+" LABFMT, q->soffset); + } else + printf("+%s", + q->soname ? q->soname : exname(q->sname)); + } + printf("\n"); + break; + case SHORT: + case USHORT: + printf("\t.short 0x%x\n", (int)p->n_lval & 0xffff); + break; + case BOOL: + if (p->n_lval > 1) + p->n_lval = p->n_lval != 0; + /* FALLTHROUGH */ + case CHAR: + case UCHAR: + /* TODO make the upper layer give an .asciz */ + printf("\t.byte %d\n", (int)p->n_lval & 0xff); + break; + case LDOUBLE: + case DOUBLE: + u.d = (double)p->n_dcon; + printf("\t.long\t0x%x,0x%x\n", u.i[0], u.i[1]); + break; + case FLOAT: + u.f = (float)p->n_dcon; + printf("\t.long\t0x%x\n", u.i[0]); + break; + default: + cerror("ninval"); + } +} + +/* make a name look like an external name in the local machine */ +char * +exname(char *p) +{ + if (p == NULL) + return ""; + return p; +} + +/* + * map types which are not defined on the local machine + */ +TWORD +ctype(TWORD type) +{ + switch (BTYPE(type)) { + case LONG: + MODTYPE(type,INT); + break; + + case ULONG: + MODTYPE(type,UNSIGNED); + } + + return (type); +} + +void +calldec(NODE *f, NODE *a) +{ + struct symtab *q; + if (f->n_op == UMUL && f->n_left->n_op == PLUS && + f->n_left->n_right->n_op == ICON) + q = f->n_left->n_right->n_sp; + else if (f->n_op == PLUS && f->n_right->n_op == ICON) + q = f->n_right->n_sp; + else { + fwalk(f, eprint, 0); + cerror("unknown function"); + return; + } + + printf("\t.import\t%s,code\n", q->soname ? q->soname : exname(q->sname)); +} + +void +extdec(struct symtab *q) +{ + printf("\t.import\t%s,data\n", q->soname ? q->soname : exname(q->sname)); +} + +/* make a common declaration for id, if reasonable */ +void +defzero(struct symtab *sp) +{ + int off; + + off = tsize(sp->stype, sp->sdf, sp->ssue); + off = (off + (SZCHAR - 1)) / SZCHAR; + printf("\t.%scomm\t", sp->sclass == STATIC ? "l" : ""); + if (sp->slevel == 0) + printf("%s,0%o\n", sp->soname ? sp->soname : exname(sp->sname), off); + else + printf(LABFMT ",0%o\n", sp->soffset, off); +} + +char * +section2string(char *name, int len) +{ + char *s; + int n; + + if (strncmp(name, "link_set", 8) == 0) { + const char *postfix = ",\"aw\",@progbits"; + n = len + strlen(postfix) + 1; + s = IALLOC(n); + strlcpy(s, name, n); + strlcat(s, postfix, n); + return s; + } + + return newstring(name, len); +} + +char *nextsect; +char *alias; +int constructor; +int destructor; + +#define SSECTION 010000 + +/* + * Give target the opportunity of handling pragmas. + */ +int +mypragma(char *str) +{ + char *a2 = pragtok(NULL); + + if (strcmp(str, "constructor") == 0 || strcmp(str, "init") == 0) { + constructor = 1; + return 1; + } + if (strcmp(str, "destructor") == 0 || strcmp(str, "fini") == 0) { + destructor = 1; + return 1; + } + if (strcmp(str, "section") == 0 && a2 != NULL) { + nextsect = section2string(a2, strlen(a2)); + return 1; + } + if (strcmp(str, "alias") == 0 && a2 != NULL) { + alias = tmpstrdup(a2); + return 1; + } + if (strcmp(str, "ident") == 0) + return 1; /* Just ignore */ + return 0; +} + +/* + * Called when a identifier has been declared, to give target last word. + */ +void +fixdef(struct symtab *sp) +{ + if (alias != NULL && (sp->sclass != PARAM)) { + printf("\t.globl %s\n%s = %s\n", exname(sp->soname), + exname(sp->soname), exname(alias)); + alias = NULL; + } + if ((constructor || destructor) && (sp->sclass != PARAM)) { + printf("\t.section .%ctors,\"aw\",@progbits\n" + "\t.p2align 2\n\t.long %s\n\t.previous\n", + constructor ? 'c' : 'd', exname(sp->sname)); + constructor = destructor = 0; + } +} + +void +pass1_lastchance(struct interpass *ip) +{ +} diff --git a/compilers/pcc/pcc-1.0.0/arch/hppa/local2.c b/compilers/pcc/pcc-1.0.0/arch/hppa/local2.c new file mode 100644 index 00000000..168d8419 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/hppa/local2.c @@ -0,0 +1,879 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2007 Michael Shalayeff + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass2.h" +# include +# include + +void acon(NODE *p); +void prtprolog(struct interpass_prolog *, int); +int countargs(NODE *p, int *); +void fixcalls(NODE *p, void *); + +static int stkpos; +int p2calls; + +static const int rl[] = + { R0, R1, R1, R1, R1, R1, R31, R31, R31, R31, + R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, R17, R18, + T1, T4, T3, T2, ARG3, ARG1, RET1 }; +static const int rh[] = + { R0, R31, T4, T3, T2, T1, T4, T3, T2, T1, + R18, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, R17, + T4, T3, T2, T1, ARG2, ARG0, RET0 }; + +void +deflab(int label) +{ + printf("\t.label\t" LABFMT "\n", label); +} + +static int regoff[MAXREGS]; +static TWORD ftype; + +/* + * Print out the prolog assembler. + * addto and regoff are already calculated. + */ +void +prtprolog(struct interpass_prolog *ipp, int addto) +{ + int i; + + /* if this functions calls nothing -- no frame is needed */ + if (p2calls || p2maxautooff > 4) { + printf("\tcopy\t%%r3,%%r1\n\tcopy\t%%sp,%%r3\n"); + if (addto < 0x2000) + printf("\tstw,ma\t%%r1,%d(%%sp)\n", addto); + else if (addto < 0x802000) + printf("\tstw,ma\t%%r1,8192(%%sp)\n" + "\taddil\t%d-8192,%%sp\n" + "\tcopy\t%%r1,%%sp\n", addto); + else + comperr("too much local allocation"); + if (p2calls) + printf("\tstw\t%%rp,-20(%%r3)\n"); + } + + for (i = 0; i < MAXREGS; i++) + if (TESTBIT(ipp->ipp_regs, i)) { + if (i <= R31) + printf("\tstw\t%s,%d(%%r3)\n", + rnames[i], regoff[i]); + else if (i <= RETD0) + printf("\tstw\t%s,%d(%%r3)\n" + "\tstw\t%s,%d(%%r3)\n", + rnames[rl[i - RD0]], regoff[i] + 0, + rnames[rh[i - RD0]], regoff[i] + 4); + else if (i <= FR31) + printf("\tfstws\t%s,%d(%%r3)\n", + rnames[i], regoff[i]); + else + printf("\tfstds\t%s,%d(%%r3)\n", + rnames[i], regoff[i]); + } +} + +/* + * calculate stack size and offsets + */ +static int +offcalc(struct interpass_prolog *ipp) +{ + int i, addto, off; + + addto = 32; + if (p2calls) { + i = p2calls - 1; + /* round up to 4 args */ + if (i < 4) + i = 4; + addto += i * 4; + } + + for (off = 4, i = 0; i < MAXREGS; i++) + if (TESTBIT(ipp->ipp_regs, i)) { + regoff[i] = off; + off += szty(PERMTYPE(i)) * SZINT/SZCHAR; + } + addto += off + p2maxautooff; + return (addto + 63) & ~63; +} + +void +prologue(struct interpass_prolog *ipp) +{ + int addto; + + ftype = ipp->ipp_type; + + /* + * We here know what registers to save and how much to + * add to the stack. + */ + addto = offcalc(ipp); + printf("\t.proc\ncallinfo frame=%d, save_rp, save_sp\n\t.entry\n", + addto); + prtprolog(ipp, addto); +} + +void +eoftn(struct interpass_prolog *ipp) +{ + int i; + + if (ipp->ipp_ip.ip_lbl == 0) + return; /* no code needs to be generated */ + + /* return from function code */ + for (i = 0; i < MAXREGS; i++) + if (TESTBIT(ipp->ipp_regs, i)) { + if (i <= R31) + printf("\tldw\t%d(%%r3),%s\n", + regoff[i], rnames[i]); + else if (i <= RETD0) + printf("\tldw\t%d(%%r3),%s\n" + "\tldw\t%d(%%r3),%s\n", + regoff[i] + 0, rnames[rl[i - RD0]], + regoff[i] + 4, rnames[rh[i - RD0]]); + else if (i <= FR31) + printf("\tfldws\t%d(%%r3),%s\n", + regoff[i], rnames[i]); + else + printf("\tfldds\t%d(%%r3),%s\n", + regoff[i], rnames[i]); + } + + if (p2calls || p2maxautooff > 4) { + if (p2calls) + printf("\tldw\t-20(%%r3),%%rp\n"); + printf("\tcopy\t%%r3,%%r1\n" + "\tldw\t0(%%r3),%%r3\n" + "\tbv\t%%r0(%%rp)\n" + "\tcopy\t%%r1,%%sp\n"); + } else + printf("\tbv\t%%r0(%%rp)\n\tnop\n"); + + printf("\t.exit\n\t.procend\n\t.size\t%s, .-%s\n", + ipp->ipp_name, ipp->ipp_name); +} + +/* + * add/sub/... + * + * Param given: + */ +void +hopcode(int f, int o) +{ + char *str; + + switch (o) { + case PLUS: + str = "add"; + break; + case MINUS: + str = "sub"; + break; + case AND: + str = "and"; + break; + case OR: + str = "or"; + break; + case ER: + str = "xor"; + break; + case EQ: + str = "="; + break; + case NE: + str = "<>"; + break; + case LE: + str = "<"; + break; + case LT: + str = "<="; + break; + case ULE: + str = "<<"; + break; + case ULT: + str = "<<="; + break; + case GE: + str = ">="; + break; + case GT: + str = ">"; + break; + case UGE: + str = ">>"; + break; + case UGT: + str = ">>="; + break; + default: + comperr("hopcode2: %d", o); + str = 0; /* XXX gcc */ + } + printf("%s%c", str, f); +} + +/* + * Return type size in bytes. Used by R2REGS, arg 2 to offset(). + */ +int +tlen(p) NODE *p; +{ + switch(p->n_type) { + case CHAR: + case UCHAR: + return(1); + + case SHORT: + case USHORT: + return(SZSHORT/SZCHAR); + + case FLOAT: + return(SZFLOAT/SZCHAR); + + case DOUBLE: + return(SZDOUBLE/SZCHAR); + + case INT: + case UNSIGNED: + case LONG: + case ULONG: + return(SZINT/SZCHAR); + + case LONGLONG: + case ULONGLONG: + return SZLONGLONG/SZCHAR; + + default: + if (!ISPTR(p->n_type)) + comperr("tlen type %d not pointer", p->n_type); + return SZPOINT(p->n_type)/SZCHAR; + } +} + +static int +argsiz(NODE *p) +{ + NODE *q; + TWORD t = p->n_type; + + if (t < LONGLONG || t == FLOAT || t > BTMASK) + return 4; + if (t == LONGLONG || t == ULONGLONG || t == DOUBLE) + return 8; + if (t == LDOUBLE) + return 8; /* LDOUBLE is 16 */ + if ((t == STRTY || t == UNIONTY) && p->n_right->n_op == STARG) + return 4 + p->n_right->n_stsize; + /* perhaps it's down there somewhere -- let me take another look! */ + if ((t == STRTY || t == UNIONTY) && p->n_right->n_op == CALL) { + q = p->n_right->n_right->n_left->n_left->n_right; + if (q->n_op == STARG) + return 4 + q->n_stsize; + } + comperr("argsiz %p", p); + return 0; +} + +/* + * Emit code to compare two longlong numbers. + */ +static void +twollcomp(NODE *p) +{ + int o = p->n_op; + int s = getlab2(); + int e = p->n_label; + int cb1, cb2; + + if (o >= ULE) + o -= (ULE-LE); + switch (o) { + case NE: + cb1 = 0; + cb2 = NE; + break; + case EQ: + cb1 = NE; + cb2 = 0; + break; + case LE: + case LT: + cb1 = GT; + cb2 = LT; + break; + case GE: + case GT: + cb1 = LT; + cb2 = GT; + break; + + default: + cb1 = cb2 = 0; /* XXX gcc */ + } + if (p->n_op >= ULE) + cb1 += 4, cb2 += 4; + if (cb1) { + p->n_op = cb1; + p->n_label = s; + expand(p, 0, "\tcomb,O\tUR,UL,LC\n\tnop\n"); + p->n_label = e; + p->n_op = o; + } + if (cb2) { + p->n_op = cb2; + expand(p, 0, "\tcomb,O\tUR,UL,LC\n\tnop\n"); + p->n_op = o; + } + expand(p, 0, "\tcomb,O\tAR,AL,LC\n\tnop\n"); + deflab(s); +} + +void +zzzcode(NODE *p, int c) +{ + int n; + + switch (c) { + + case 'C': /* after-call fixup */ + n = p->n_qual; /* args */ + break; + + case 'P': /* returning struct-call setup */ + n = p->n_qual; /* args */ + break; + + case 'D': /* Long long comparision */ + twollcomp(p); + break; + + case 'F': /* struct as an arg */ + + default: + comperr("zzzcode %c", c); + } +} + +int canaddr(NODE *); +int +canaddr(NODE *p) +{ + int o = p->n_op; + + if (o == NAME || o == REG || o == ICON || o == OREG || + (o == UMUL && shumul(p->n_left, SOREG))) + return(1); + return(0); +} + +int +fldexpand(NODE *p, int cookie, char **cp) +{ + return 0; +} + +/* + * Does the bitfield shape match? + */ +int +flshape(NODE *p) +{ + if (isreg(p)) + return SRDIR; /* Direct match */ + + return SRREG; /* put it into a register */ +} + +/* INTEMP shapes must not contain any temporary registers */ +/* XXX should this go away now? */ +int +shtemp(NODE *p) +{ + return 0; +#if 0 + int r; + + if (p->n_op == STARG ) + p = p->n_left; + + switch (p->n_op) { + case REG: + return (!istreg(p->n_rval)); + + case OREG: + r = p->n_rval; + if (R2TEST(r)) { + if (istreg(R2UPK1(r))) + return(0); + r = R2UPK2(r); + } + return (!istreg(r)); + + case UMUL: + p = p->n_left; + return (p->n_op != UMUL && shtemp(p)); + } + + if (optype(p->n_op) != LTYPE) + return(0); + return(1); +#endif +} + +void +adrcon(CONSZ val) +{ + /* fix for L% and R% */ + printf(CONFMT, val); +} + +void +conput(FILE *fp, NODE *p) +{ + CONSZ val = p->n_lval; + + switch (p->n_op) { + case ICON: + if (p->n_name[0] != '\0') { + fprintf(fp, "RR'%s-$global$", p->n_name); + if (val) + fprintf(fp, "+" CONFMT, val); + } else + fprintf(fp, CONFMT, val); + return; + + default: + comperr("illegal conput, p %p", p); + } +} + +/*ARGSUSED*/ +void +insput(NODE *p) +{ + comperr("insput"); +} + +/* + * Write out the upper address, like the upper register of a 2-register + * reference, or the next memory location. + */ +void +upput(NODE *p, int size) +{ + + size /= SZCHAR; + switch (p->n_op) { + case REG: + printf("%s", rnames[rh[p->n_rval - RD0]]); + break; + + case OREG: + p->n_lval += size; + adrput(stdout, p); + p->n_lval -= size; + break; + + case ICON: + case NAME: + if (p->n_name[0] != '\0') { + printf("LR'%s-$global$", p->n_name); + if (p->n_lval != 0) + printf("+" CONFMT, p->n_lval); + } else + printf("L%%" CONFMT, p->n_lval >> 32); + break; + default: + comperr("upput bad op %d size %d", p->n_op, size); + } +} + +void +adrput(FILE *io, NODE *p) +{ + int r; + /* output an address, with offsets, from p */ + + if (p->n_op == FLD) + p = p->n_left; + + switch (p->n_op) { + + case ICON: + case NAME: + if (p->n_name[0] != '\0') { + fprintf(io, "RR'%s-$global$", p->n_name); + if (p->n_lval != 0) + fprintf(io, "+" CONFMT, p->n_lval); + } else + fprintf(io, "R%%" CONFMT, p->n_lval); + return; + + case OREG: + r = p->n_rval; + if (p->n_name[0] != '\0') { + fprintf(io, "RR'%s-$global$", p->n_name); + if (p->n_lval != 0) + fprintf(io, "+" CONFMT, p->n_lval); + } else + fprintf(io, "%d", (int)p->n_lval); + if (R2TEST(r)) { + fprintf(io, "%s(%s)", rnames[R2UPK1(r)], + rnames[R2UPK2(r)]); + } else + fprintf(io, "(%s)", rnames[p->n_rval]); + return; + case REG: + if (RD0 <= p->n_rval && p->n_rval <= RETD0) + fprintf(io, "%s", rnames[rl[p->n_rval - RD0]]); + else + fprintf(io, "%s", rnames[p->n_rval]); + return; + + default: + comperr("illegal address, op %d, node %p", p->n_op, p); + return; + + } +} + +/* not used */ +void +cbgen(int o, int lab) +{ +} + +int +countargs(NODE *p, int *n) +{ + int sz; + + if (p->n_op == CM) { + countargs(p->n_left, n); + countargs(p->n_right, n); + return *n; + } + + sz = argsiz(p) / 4; + if (*n % (sz > 4? 4 : sz)) + (*n)++; /* XXX */ + + return *n += sz; +} + +void +fixcalls(NODE *p, void *arg) +{ + int n, o; + + /* Prepare for struct return by allocating bounce space on stack */ + switch (o = p->n_op) { + case STCALL: + case USTCALL: + if (p->n_stsize + p2autooff > stkpos) + stkpos = p->n_stsize + p2autooff; + /* FALLTHROGH */ + case CALL: + case UCALL: + n = 0; + n = 1 + countargs(p->n_right, &n); + if (n > p2calls) + p2calls = n; + break; + } +} + +void +myreader(struct interpass *ipole) +{ + struct interpass *ip; + + stkpos = p2autooff; + DLIST_FOREACH(ip, ipole, qelem) { + switch (ip->type) { + case IP_PROLOG: + p2calls = 0; + break; + + case IP_NODE: + walkf(ip->ip_node, fixcalls, 0); + break; + } + } + if (stkpos > p2autooff) + p2autooff = stkpos; + if (stkpos > p2maxautooff) + p2maxautooff = stkpos; + if (x2debug) + printip(ipole); +} + +/* + * Remove some PCONVs after OREGs are created. + */ +static void +pconv2(NODE *p, void *arg) +{ + NODE *q; + + if (p->n_op == PLUS) { + if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) { + if (p->n_right->n_op != ICON) + return; + if (p->n_left->n_op != PCONV) + return; + if (p->n_left->n_left->n_op != OREG) + return; + q = p->n_left->n_left; + nfree(p->n_left); + p->n_left = q; + /* + * This will be converted to another OREG later. + */ + } + } +} + +void +mycanon(NODE *p) +{ + walkf(p, pconv2, 0); +} + +void +myoptim(struct interpass *ipole) +{ +} + +void +rmove(int s, int d, TWORD t) +{ + int sl, sh, dl, dh; + + switch (t) { + case LONGLONG: + case ULONGLONG: + sl = rl[s-RD0]; + sh = rh[s-RD0]; + dl = rl[d-RD0]; + dh = rh[d-RD0]; + +#define SW(x,y) { int i = x; x = y; y = i; } + if (sl == dh || sh == dl) { + /* Swap if moving to itself */ + SW(sl, sh); + SW(dl, dh); + } + if (sl != dl) + printf("\tcopy\t%s,%s\n", rnames[sl], rnames[dl]); + if (sh != dh) + printf("\tcopy\t%s,%s\n", rnames[sh], rnames[dh]); + break; + case FLOAT: + printf("\tfcpy,sgl\t%s,%s\n", rnames[s], rnames[d]); + break; + case DOUBLE: + case LDOUBLE: + printf("\tfcpy,dbl\t%s,%s\n", rnames[s], rnames[d]); + break; + default: + printf("\tcopy\t%s,%s\n", rnames[s], rnames[d]); + } +} + +/* + * For class c, find worst-case displacement of the number of + * registers in the array r[] indexed by class. + */ +int +COLORMAP(int c, int *r) +{ + int num; + + switch (c) { + case CLASSA: + num = 2 * r[CLASSB]; + num += r[CLASSA]; + return num < 28; + case CLASSB: + num = r[CLASSA]; + num += r[CLASSB] * 2; + return num < 28; + case CLASSC: + num = (r[CLASSD] > 8? 8 : r[CLASSD]) * 2; + num += r[CLASSC]; + return num < 28; + case CLASSD: + num = (r[CLASSC] + 1) / 2; + num += r[CLASSD]; + return num < 28; + } + return 0; /* XXX gcc */ +} + +char * rnames[MAXREGS] = { + "%r0", "%r1", "%rp", "%r3", "%r4", "%r5", "%r6", "%r7", "%r8", "%r9", + "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%r16", "%r17", "%r18", + "%t4", "%t3", "%t2", "%t1", "%arg3", "%arg2", "%arg1", "%arg0", "%dp", + "%ret0", "%ret1", "%sp", "%r31", + "%rd0", "%rd1", "%rd2", "%rd3", "%rd4", "%rd5", "%rd6", "%rd7", + "%rd8", "%rd9", "%rd10", "%rd11", "%rd12", "%rd13", "%rd14", "%rd15", + "%rd16", "%rd17", "%rd18", "%rd19", "%rd20", "%rd21", "%rd22", "%rd23", + "%rd24", "%td4", "%td3", "%td2", "%td1", "%ad1", "%ad0", "%retd0", + "%fr0", "%fr4", "%fr5", "%fr6", "%fr7", "%fr8", "%fr9", "%fr10", + "%fr11", "%fr12", "%fr13", "%fr14", "%fr15", "%fr16", "%fr17", "%fr18", + "%fr19", "%fr20", "%fr21", "%fr22", "%fr23", "%fr24", "%fr25", "%fr26", + "%fr27", "%fr28", "%fr29", "%fr30", "%fr31", + "%fr0l", "%fr0r", "%fr4l", "%fr4r", "%fr5l", "%fr5r", "%fr6l", "%fr6r", + "%fr7l", "%fr7r", "%fr8l", "%fr8r", "%fr9l", "%fr9r", + "%fr10l", "%fr10r", "%fr11l", "%fr11r", "%fr12l", "%fr12r", + "%fr13l", "%fr13r", "%fr14l", "%fr14r", "%fr15l", "%fr15r", + "%fr16l", "%fr16r", "%fr17l", "%fr17r", "%fr18l", "%fr18r", +#ifdef __hppa64__ + "%fr19l", "%fr19r", + "%fr20l", "%fr20r", "%fr21l", "%fr21r", "%fr22l", "%fr22r", + "%fr23l", "%fr23r", "%fr24l", "%fr24r", "%fr25l", "%fr25r", + "%fr26l", "%fr26r", "%fr27l", "%fr27r", "%fr28l", "%fr28r", + "%fr29l", "%fr29r", "%fr30l", "%fr30r", "%fr31l", "%fr31r", +#endif +}; + +/* + * Return a class suitable for a specific type. + */ +int +gclass(TWORD t) +{ + switch (t) { + case LONGLONG: + case ULONGLONG: + return CLASSB; + case FLOAT: + return CLASSC; + case DOUBLE: + case LDOUBLE: + return CLASSD; + default: + return CLASSA; + } +} + +/* + * Calculate argument sizes. + */ +void +lastcall(NODE *p) +{ + NODE *op = p; + int size = 64; + + p->n_qual = size; + if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL) + return; + for (p = p->n_right; p->n_op == CM; p = p->n_left) + size += argsiz(p->n_right); + size += argsiz(p); + op->n_qual = size; /* XXX */ +} + +/* + * Special shapes. + */ +int +special(NODE *p, int shape) +{ + int o = p->n_op; + + switch (shape) { + case SFUNCALL: + if (o == STCALL || o == USTCALL) + return SRREG; + break; + case SPIMM: + if (o != ICON || p->n_name[0] || + p->n_lval < -31 || p->n_lval >= 32) + break; + return SRDIR; + case SPICON: + if (o != ICON || p->n_name[0] || + p->n_lval < -1024 || p->n_lval >= 1024) + break; + return SRDIR; + case SPCNHW: + if (o != ICON || p->n_name[0] || (p->n_lval & 0xffffffffLL)) + break; + return SRDIR; + case SPCNLW: + if (o != ICON || p->n_name[0] || (p->n_lval & ~0xffffffffLL)) + break; + return SRDIR; + case SPCNHI: + if (o != ICON || p->n_name[0] || (p->n_lval & ~0xfffff800LL)) + break; + return SRDIR; + case SPCON: + if (o != ICON || p->n_name[0] || + p->n_lval < -8192 || p->n_lval >= 8192) + break; + return SRDIR; + case SPNAME: + if (o != ICON || !p->n_name[0]) + break; + return SRDIR; + } + return SRNOPE; +} + +/* + * Target-dependent command-line options. + */ +void +mflags(char *str) +{ +} +/* + * Do something target-dependent for xasm arguments. + * Supposed to find target-specific constraints and rewrite them. + */ +int +myxasm(struct interpass *ip, NODE *p) +{ + return 0; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/hppa/macdefs.h b/compilers/pcc/pcc-1.0.0/arch/hppa/macdefs.h new file mode 100644 index 00000000..fbf6a482 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/hppa/macdefs.h @@ -0,0 +1,473 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2007 Michael Shalayeff + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Convert (multi-)character constant to integer. + */ +#define makecc(val,i) (lastcon = (lastcon<<8)|((val<<24)>>24)) + +#define ARGINIT (32*8) /* bits below fp where args start */ +#define AUTOINIT (4*8) /* bits above fp where locals start */ + +/* + * storage sizes + */ +#define SZCHAR 8 +#define SZBOOL 8 +#define SZINT 32 +#define SZFLOAT 32 +#define SZDOUBLE 64 +#define SZLDOUBLE 64 /* or later 128 */ +#define SZLONG 32 +#define SZSHORT 16 +#define SZLONGLONG 64 +#define SZPOINT(t) 32 + +/* + * alignment requirements + */ +#define ALCHAR 8 +#define ALBOOL 8 +#define ALINT 32 +#define ALFLOAT 32 +#define ALDOUBLE 64 +#define ALLDOUBLE 64 /* 128 later */ +#define ALLONG 32 +#define ALLONGLONG 32 +#define ALSHORT 16 +#define ALPOINT 32 +#define ALSTRUCT 32 +#define ALSTACK 64 + +/* + * type value limits + */ +#define MIN_CHAR -128 +#define MAX_CHAR 127 +#define MAX_UCHAR 255 +#define MIN_SHORT -32768 +#define MAX_SHORT 32767 +#define MAX_USHORT 65535 +#define MIN_INT (-0x7fffffff-1) +#define MAX_INT 0x7fffffff +#define MAX_UNSIGNED 0xffffffff +#define MIN_LONG MIN_INT +#define MAX_LONG MAX_INT +#define MAX_ULONG MAX_UNSIGNED +#define MIN_LONGLONG (-0x7fffffffffffffffLL-1) +#define MAX_LONGLONG 0x7fffffffffffffffLL +#define MAX_ULONGLONG 0xffffffffffffffffULL + +#undef CHAR_UNSIGNED +#define BOOL_TYPE CHAR +#define ENUMSIZE(high,low) INT + +typedef long long CONSZ; +typedef unsigned long long U_CONSZ; +typedef long long OFFSZ; + +#define CONFMT "%lld" /* format for printing constants */ +#define LABFMT ".L%d" /* format for printing labels */ +#define STABLBL ".LL%d" /* format for stab (debugging) labels */ + +#undef BACKAUTO /* stack grows upwards */ +#undef BACKTEMP /* stack grows upwards */ + +#define FIELDOPS /* have bit field ops */ +#define LTORBYTES /* big endian */ + +#define BYTEOFF(x) ((x)&03) +#define wdal(k) (BYTEOFF(k)==0) +#define BITOOR(x) (x) /* bit offset to oreg offset XXX die! */ + +#define STOARG(p) +#define STOFARG(p) +#define STOSTARG(p) + +#define szty(t) (((t) == DOUBLE || (t) == LONGLONG || (t) == ULONGLONG) ? 2 : \ + (t) == LDOUBLE ? 2 : 1) + +#define R0 0 +#define R1 1 +#define RP 2 +#define FP 3 +#define R4 4 +#define R5 5 +#define R6 6 +#define R7 7 +#define R8 8 +#define R9 9 +#define R10 10 +#define R11 11 +#define R12 12 +#define R13 13 +#define R14 14 +#define R15 15 +#define R16 16 +#define R17 17 +#define R18 18 +#define T4 19 +#define T3 20 +#define T2 21 +#define T1 22 +#define ARG3 23 +#define ARG2 24 +#define ARG1 25 +#define ARG0 26 +#define DP 27 +#define RET0 28 +#define RET1 29 +#define SP 30 +#define R31 31 + +/* double regs overlay */ +#define RD0 32 /* r0:r0 */ +#define RD1 33 /* r1:r31 */ +#define RD2 34 /* r1:t4 */ +#define RD3 35 /* r1:t3 */ +#define RD4 36 /* r1:t2 */ +#define RD5 37 /* r1:t1 */ +#define RD6 38 /* r31:t4 */ +#define RD7 39 /* r31:t3 */ +#define RD8 40 /* r31:t2 */ +#define RD9 41 /* r31:t1 */ +#define RD10 42 /* r4:r18 */ +#define RD11 43 /* r5:r4 */ +#define RD12 44 /* r6:r5 */ +#define RD13 45 /* r7:r6 */ +#define RD14 46 /* r8:r7 */ +#define RD15 47 /* r9:r8 */ +#define RD16 48 /* r10:r9 */ +#define RD17 49 /* r11:r10 */ +#define RD18 50 /* r12:r11 */ +#define RD19 51 /* r13:r12 */ +#define RD20 52 /* r14:r13 */ +#define RD21 53 /* r15:r14 */ +#define RD22 54 /* r16:r15 */ +#define RD23 55 /* r17:r16 */ +#define RD24 56 /* r18:r17 */ +#define TD4 57 /* t1:t4 */ +#define TD3 58 /* t4:t3 */ +#define TD2 59 /* t3:t2 */ +#define TD1 60 /* t2:t1 */ +#define AD2 61 /* arg3:arg2 */ +#define AD1 62 /* arg1:arg0 */ +#define RETD0 63 /* ret1:ret0 */ + +/* FPU regs */ +#define FR0 64 +#define FR4 65 +#define FR5 66 +#define FR6 67 +#define FR7 68 +#define FR8 69 +#define FR9 70 +#define FR10 71 +#define FR11 72 +#define FR12 73 +#define FR13 74 +#define FR14 75 +#define FR15 76 +#define FR16 77 +#define FR17 78 +#define FR18 79 +#define FR19 80 +#define FR20 81 +#define FR21 82 +#define FR22 83 +#define FR23 84 +#define FR24 85 +#define FR25 86 +#define FR26 87 +#define FR27 88 +#define FR28 89 +#define FR29 90 +#define FR30 91 +#define FR31 92 + +#define FR0L 93 +#define FR0R 94 +#define FR4L 95 +#define FR4R 96 +#define FR5L 97 +#define FR5R 98 +#define FR6L 99 +#define FR6R 100 +#define FR7L 101 +#define FR7R 102 +#define FR8L 103 +#define FR8R 104 +#define FR9L 105 +#define FR9R 106 +#define FR10L 107 +#define FR10R 108 +#define FR11L 109 +#define FR11R 110 +#define FR12L 111 +#define FR12R 112 +#define FR13L 113 +#define FR13R 114 +#define FR14L 115 +#define FR14R 116 +#define FR15L 117 +#define FR15R 118 +#define FR16L 119 +#define FR16R 120 +#define FR17L 121 +#define FR17R 122 +#define FR18L 123 +#define FR18R 124 +#ifdef __hppa64__ +#define FR19L 125 +#define FR19R 126 +#define FR20L 127 +#define FR20R 128 +#define FR21L 129 +#define FR21R 130 +#define FR22L 131 +#define FR22R 132 +#define FR23L 133 +#define FR23R 134 +#define FR24L 135 +#define FR24R 136 +#define FR25L 137 +#define FR25R 138 +#define FR26L 139 +#define FR26R 140 +#define FR27L 141 +#define FR27R 142 +#define FR28L 143 +#define FR28R 144 +#define FR29L 145 +#define FR29R 146 +#define FR30L 147 +#define FR30R 148 +#define FR31L 149 +#define FR31R 150 + +#define MAXREGS 151 +#else +#define MAXREGS 125 +#endif + +#define RSTATUS \ + 0, SAREG|TEMPREG, 0, 0, SAREG|PERMREG, SAREG|PERMREG, \ + SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, \ + SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, \ + SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, \ + SAREG|PERMREG, \ + SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \ + SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \ + 0, SAREG|TEMPREG, SAREG|TEMPREG, 0, SAREG|TEMPREG, \ + /* double overlays */ \ + 0, \ + SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \ + SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \ + SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \ + SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \ + /* double-precision floats */ \ + 0, \ + SDREG|TEMPREG, SDREG|TEMPREG, SDREG|TEMPREG, SDREG|TEMPREG, \ + SDREG|TEMPREG, SDREG|TEMPREG, SDREG|TEMPREG, SDREG|TEMPREG, \ + SDREG|PERMREG, SDREG|PERMREG, SDREG|PERMREG, SDREG|PERMREG, \ + SDREG|PERMREG, SDREG|PERMREG, SDREG|PERMREG, SDREG|PERMREG, \ + SDREG|PERMREG, SDREG|PERMREG, \ + SDREG|TEMPREG, SDREG|TEMPREG, SDREG|TEMPREG, SDREG|TEMPREG, \ + SDREG|TEMPREG, SDREG|TEMPREG, SDREG|TEMPREG, SDREG|TEMPREG, \ + SDREG|TEMPREG, SDREG|TEMPREG, \ + /* single-precision floats */ \ + 0, 0, \ + SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \ + SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \ + SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \ + SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, +#ifdef __hppa64__ + SCREG, SCREG, \ + SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \ + SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \ + SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, +#endif + +#define ROVERLAP \ + { -1 }, \ + { RD1, RD2, RD3, RD4, RD5, -1 },\ + { -1 }, { -1 }, \ + { RD10, RD11, -1 }, \ + { RD11, RD12, -1 }, \ + { RD12, RD13, -1 }, \ + { RD13, RD14, -1 }, \ + { RD14, RD15, -1 }, \ + { RD15, RD16, -1 }, \ + { RD16, RD17, -1 }, \ + { RD17, RD18, -1 }, \ + { RD18, RD19, -1 }, \ + { RD19, RD20, -1 }, \ + { RD20, RD21, -1 }, \ + { RD21, RD22, -1 }, \ + { RD22, RD23, -1 }, \ + { RD23, RD24, -1 }, \ + { RD24, RD10, -1 }, \ + { TD1, TD4, -1 }, \ + { TD3, TD2, -1 }, \ + { TD1, TD2, -1 }, \ + { TD1, TD4, -1 }, \ + { AD2, -1 }, { AD2, -1 }, \ + { AD1, -1 }, { AD1, -1 }, \ + { -1 }, \ + { RETD0, -1 }, { RETD0, -1 }, \ + { -1 }, \ + { RD1, RD5, RD6, RD7, RD8, -1 },\ + { -1 }, \ + { R1, R31, -1 }, \ + { R1, T4, -1 }, \ + { R1, T3, -1 }, \ + { R1, T2, -1 }, \ + { R1, T1, -1 }, \ + { R31, T4, -1 }, \ + { R31, T3, -1 }, \ + { R31, T2, -1 }, \ + { R31, T1, -1 }, \ + { R4, R18, -1 }, \ + { R5, R4, -1 }, \ + { R6, R5, -1 }, \ + { R7, R6, -1 }, \ + { R8, R7, -1 }, \ + { R9, R8, -1 }, \ + { R10, R9, -1 }, \ + { R11, R10, -1 }, \ + { R12, R11, -1 }, \ + { R13, R12, -1 }, \ + { R14, R15, -1 }, \ + { R15, R14, -1 }, \ + { R16, R15, -1 }, \ + { R17, R16, -1 }, \ + { R18, R17, -1 }, \ + { T1, T4, -1 }, \ + { T4, T3, -1 }, \ + { T3, T2, -1 }, \ + { T2, T1, -1 }, \ + { ARG3, ARG2, -1 }, \ + { ARG1, ARG0, -1 }, \ + { RET1, RET0, -1 }, \ + { -1 }, \ + { FR4L, FR4R, -1 }, \ + { FR5L, FR5R, -1 }, \ + { FR6L, FR6R, -1 }, \ + { FR7L, FR7R, -1 }, \ + { FR8L, FR8R, -1 }, \ + { FR9L, FR9R, -1 }, \ + { FR10L, FR10R, -1 }, \ + { FR11L, FR11R, -1 }, \ + { FR12L, FR12R, -1 }, \ + { FR13L, FR13R, -1 }, \ + { FR14L, FR14R, -1 }, \ + { FR15L, FR15R, -1 }, \ + { FR16L, FR16R, -1 }, \ + { FR17L, FR17R, -1 }, \ + { FR18L, FR18R, -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, { -1 }, \ + { FR4, -1 }, { FR4, -1 }, \ + { FR5, -1 }, { FR5, -1 }, \ + { FR6, -1 }, { FR6, -1 }, \ + { FR7, -1 }, { FR7, -1 }, \ + { FR8, -1 }, { FR8, -1 }, \ + { FR9, -1 }, { FR9, -1 }, \ + { FR10, -1 }, { FR10, -1 }, \ + { FR11, -1 }, { FR11, -1 }, \ + { FR12, -1 }, { FR12, -1 }, \ + { FR13, -1 }, { FR13, -1 }, \ + { FR14, -1 }, { FR14, -1 }, \ + { FR15, -1 }, { FR15, -1 }, \ + { FR16, -1 }, { FR16, -1 }, \ + { FR17, -1 }, { FR17, -1 }, \ + { FR18, -1 }, { FR18, -1 }, +#ifdef __hppa64__ + { FR19, -1 }, { FR19, -1 }, \ + { FR20, -1 }, { FR20, -1 }, \ + { FR21, -1 }, { FR21, -1 }, \ + { FR22, -1 }, { FR22, -1 }, \ + { FR23, -1 }, { FR23, -1 }, \ + { FR24, -1 }, { FR24, -1 }, \ + { FR25, -1 }, { FR25, -1 }, \ + { FR26, -1 }, { FR26, -1 }, \ + { FR27, -1 }, { FR27, -1 }, \ + { FR28, -1 }, { FR28, -1 }, \ + { FR29, -1 }, { FR29, -1 }, \ + { FR30, -1 }, { FR30, -1 }, \ + { FR31, -1 }, { FR31, -1 }, +#endif + +#define PCLASS(p) \ + (p->n_type == LONGLONG || p->n_type == ULONGLONG ? SBREG : \ + (p->n_type == FLOAT ? SCREG : \ + (p->n_type == DOUBLE || p->n_type == LDOUBLE ? SDREG : SAREG))) + +#define NUMCLASS 4 /* highest number of reg classes used */ + +int COLORMAP(int c, int *r); +#define PERMTYPE(x) ((x) < 32? INT : ((x) < 64? LONGLONG : ((x) < 93? LDOUBLE : FLOAT))) +#define GCLASS(x) ((x) < 32? CLASSA : ((x) < 64? CLASSB : ((x) < 93? CLASSD : CLASSC))) +#define DECRA(x,y) (((x) >> (y*8)) & 255) /* decode encoded regs */ +#define ENCRD(x) (x) /* Encode dest reg in n_reg */ +#define ENCRA1(x) ((x) << 8) /* A1 */ +#define ENCRA2(x) ((x) << 16) /* A2 */ +#define ENCRA(x,y) ((x) << (8+y*8)) /* encode regs in int */ +#define RETREG(x) (x == LONGLONG || x == ULONGLONG ? RETD0 : \ + x == FLOAT? FR4L : \ + x == DOUBLE || x == LDOUBLE ? FR4 : RET0) + +#define FPREG FP /* frame pointer */ +#define STKREG SP /* stack pointer */ + +#define MYREADER(p) myreader(p) +#define MYCANON(p) mycanon(p) +#define MYOPTIM + +#define SFUNCALL (MAXSPECIAL+1) /* struct assign after function call */ +#define SPCNHI (MAXSPECIAL+2) /* high 21bits constant */ +#define SPCON (MAXSPECIAL+3) /* smaller constant */ +#define SPICON (MAXSPECIAL+4) /* even smaller constant */ +#define SPCNHW (MAXSPECIAL+5) /* LL const w/ 0 in low word */ +#define SPCNLW (MAXSPECIAL+6) /* LL const w/ 0 in high word */ +#define SPIMM (MAXSPECIAL+7) /* immidiate const for depi/comib */ +#define SPNAME (MAXSPECIAL+8) /* ext symbol reference load/store */ diff --git a/compilers/pcc/pcc-1.0.0/arch/hppa/order.c b/compilers/pcc/pcc-1.0.0/arch/hppa/order.c new file mode 100644 index 00000000..5ae5489f --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/hppa/order.c @@ -0,0 +1,216 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2007 Michael Shalayeff + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass2.h" + +#include + +int canaddr(NODE *); + +/* is it legal to make an OREG or NAME entry which has an + * offset of off, (from a register of r), if the + * resulting thing had type t */ +int +notoff(TWORD t, int r, CONSZ off, char *cp) +{ + return(0); /* YES */ +} + +/* + * Turn a UMUL-referenced node into OREG. + * Be careful about register classes, this is a place where classes change. + */ +void +offstar(NODE *p, int shape) +{ + NODE *r; + + if (x2debug) + printf("offstar(%p)\n", p); + + if (isreg(p)) + return; /* Is already OREG */ + + r = p->n_right; + if (p->n_op == PLUS || p->n_op == MINUS) { + if (r->n_op == ICON) { + if (isreg(p->n_left) == 0) + (void)geninsn(p->n_left, INAREG); + /* Converted in ormake() */ + return; + } + } + (void)geninsn(p, INAREG); +} + +/* + * Do the actual conversion of offstar-found OREGs into real OREGs. + */ +void +myormake(NODE *q) +{ + NODE *p, *r; + + if (x2debug) + printf("myormake(%p)\n", q); + + p = q->n_left; + if (p->n_op == PLUS && (r = p->n_right)->n_op == LS && + r->n_right->n_op == ICON && r->n_right->n_lval == 2 && + p->n_left->n_op == REG && r->n_left->n_op == REG) { + q->n_op = OREG; + q->n_lval = 0; + q->n_rval = R2PACK(p->n_left->n_rval, r->n_left->n_rval, 0); + tfree(p); + } +} + +/* + * Shape matches for UMUL. Cooperates with offstar(). + */ +int +shumul(NODE *p, int shape) +{ + + if (x2debug) + printf("shumul(%p)\n", p); + + /* Turns currently anything into OREG on hppa */ + if (shape & SOREG) + return SOREG; + return SRNOPE; +} + +/* + * Rewrite operations on binary operators (like +, -, etc...). + * Called as a result of table lookup. + */ +int +setbin(NODE *p) +{ + if (x2debug) + printf("setbin(%p)\n", p); + + return 0; +} + +/* setup for assignment operator */ +int +setasg(NODE *p, int cookie) +{ + if (x2debug) + printf("setasg(%p,%s)\n", p, prcook(cookie)); + + if (p->n_left->n_op == FLD && !isreg(p->n_left->n_left)) { + NODE *l, *r; + int reg; + + geninsn(p->n_left->n_left, INAREG); + + reg = DECRA(p->n_left->n_left->n_reg, 0); + l = tcopy(p->n_left->n_left); + p->n_left->n_left->n_op = REG; + p->n_left->n_left->n_rval = reg; + p->n_left->n_left->n_lval = 0; + r = tcopy(p->n_left->n_left); + + geninsn(p->n_left, INAREG); + l = mkbinode(ASSIGN, l, r, l->n_type); + geninsn(l, INAREG); + return (1); + } + + return (0); +} + +/* setup for unary operator */ +int +setuni(NODE *p, int cookie) +{ + if (x2debug) + printf("setuni(%p,%s)\n", p, prcook(cookie)); + + return 0; +} + +/* + * Special handling of some instruction register allocation. + */ +struct rspecial * +nspecial(struct optab *q) +{ + comperr("nspecial entry %d", q - table); + return 0; /* XXX gcc */ +} + +/* + * Set evaluation order of a binary node if it differs from default. + */ +int +setorder(NODE *p) +{ + return 0; /* nothing differs on hppa */ +} + +/* + * Set registers "live" at function calls (like arguments in registers). + * This is for liveness analysis of registers. + */ +int * +livecall(NODE *p) +{ + static int r[5], *s = &r[4]; + + *s = -1; + if (p->n_op == UCALL || p->n_op == UFORTCALL || p->n_op == USTCALL || + p->n_op == FORTCALL) + return s; + + for (p = p->n_right; p->n_op == CM; p = p->n_left) + if (p->n_right->n_op == ASSIGN && + p->n_right->n_left->n_op == REG) + *--s = p->n_right->n_left->n_rval; + + if (p->n_op == ASSIGN && + p->n_left->n_op == REG) + *--s = p->n_left->n_rval; + + return s; +} + +/* + * Signal whether the instruction is acceptable for this target. + */ +int +acceptable(struct optab *op) +{ + return 1; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/hppa/table.c b/compilers/pcc/pcc-1.0.0/arch/hppa/table.c new file mode 100644 index 00000000..467db656 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/hppa/table.c @@ -0,0 +1,1014 @@ +/* $OpenBSD: table.c,v 1.2 2007/12/19 20:19:54 otto Exp $ */ + +/* + * Copyright (c) 2007 Michael Shalayeff + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "pass2.h" + +#define TLL TLONGLONG|TULONGLONG +#define ANYSIGNED TINT|TLONG|TSHORT|TCHAR +#define ANYUSIGNED TUNSIGNED|TULONG|TUSHORT|TUCHAR +#define ANYFIXED ANYSIGNED|ANYUSIGNED +#define TUWORD TUNSIGNED|TULONG +#define TSWORD TINT|TLONG +#define TWORD TUWORD|TSWORD +#define THWORD TUSHORT|TSHORT +#define TBYTE TUCHAR|TCHAR + +#define SHINT SAREG /* char, short and int */ +#define ININT INAREG +#define SHLL SBREG /* shape for long long */ +#define INLL INBREG +#define SHFL SCREG /* shape for float */ +#define INFL INCREG +#define SHDBL SDREG /* shape for double */ +#define INDBL INDREG + +struct optab table[] = { +/* First entry must be an empty entry */ +{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", }, + +/* PCONVs are usually not necessary */ +{ PCONV, INAREG, + SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + 0, RLEFT, + "", }, +/* + * A bunch conversions of integral<->integral types + * There are lots of them, first in table conversions to itself + * and then conversions from each type to the others. + */ + +/* itself to itself, including pointers */ + +/* convert int,short,char <-> int,short,char. */ +{ SCONV, ININT, + SHINT, TBYTE, + SHINT, TBYTE, + 0, RLEFT, + "", }, + +{ SCONV, ININT, + SHINT, THWORD, + SHINT, THWORD, + 0, RLEFT, + "", }, + +{ SCONV, ININT, + SHINT, TWORD, + SHINT, TWORD, + 0, RLEFT, + "", }, + +/* convert pointers to int. */ +{ SCONV, ININT, + SHINT, TWORD|TPOINT, + SANY, TWORD, + 0, RLEFT, + "", }, + +/* convert (u)longlong to (u)longlong. */ +{ SCONV, INLL, + SHLL, TLL, + SHLL, TLL, + 0, RLEFT, + "", }, + +/* convert pointers to pointers. */ +{ SCONV, ININT, + SHINT, TPOINT, + SANY, TPOINT, + 0, RLEFT, + "", }, + +/* convert double <-> ldouble. nothing to do here (or support quads later) */ +{ SCONV, INDBL, + SHDBL, TDOUBLE|TLDOUBLE, + SHDBL, TDOUBLE|TLDOUBLE, + 0, RLEFT, + "", }, + +/* convert float -> double */ +{ SCONV, INFL, + SHFL, TFLOAT, + SHDBL, TDOUBLE|TLDOUBLE, + 0, 0, + "\tfcnvff,sgl,dbl AL,AR\n", }, + +/* convert double -> float */ +{ SCONV, INDBL, + SHDBL, TDOUBLE|TLDOUBLE, + SHFL, TFLOAT, + 0, 0, + "\tfcnvff,dbl,sgl\tAL,AR\n", }, + +/* convert int,short,char to (u)long long */ +{ SCONV, INLL, + SHINT, ANYSIGNED, + SANY, TLL, + NBREG, RESC1, + "\tcopy\tAL,A1\n" + "\textrs\tAL,0,1,U1\n", }, + +/* convert unsigned int,short,char to (u)long long */ +{ SCONV, INLL, + SHINT, TWORD, + SANY, TLL, + NBREG, RESC1, + "\tcopy\tAL,A1\n" + "\tcopy\t%r0,U1\n", }, + +/* convert int,short,char (in memory) to float */ +{ SCONV, INFL, + SOREG, ANYSIGNED, + SHFL, TFLOAT, + NCREG, RESC1, + "\tfldws\tAL,A1\n" + "\tfcnvxf,sgl,sgl\tA1,A1\n", }, + +/* convert int,short,char (in memory) to double */ +{ SCONV, INDBL, + SOREG, TSWORD, + SHDBL, TDOUBLE|TLDOUBLE, + NDREG, RESC1, + "\tfldws\tAL,A1\n" + "\tfcnvxf,sgl,dbl\tA1,A1\n", }, + +/* convert (u)long (in memory) to double */ +{ SCONV, INDBL, + SOREG, TLL, + SHDBL, TDOUBLE|TLDOUBLE, + NDREG, RESC1, + "\tfldds\tAL,A1\n" + "\tfcnvxf,dbl,dbl\tA1,A1\n", }, + +/* convert int,short,char (in register) to float */ +{ SCONV, INFL, + SHINT, TSWORD, + SHFL, TFLOAT, + NCREG, RESC1, + "\tstw,ma\tAL,4(%sp)\n" + "\tfldws,ma\t-4(%sp),A1\n" + "\tfcnvxf,sgl,sgl\tA1,A1\n", }, + +/* convert int,short,char (in register) to double */ +{ SCONV, INDBL, + SHINT, TSWORD, + SHDBL, TDOUBLE|TLDOUBLE, + NDREG, RESC1, + "\tstw,ma\tAL,4(%sp)\n" + "\tfldws,mb\t-4(%sp),AR\n" + "\tfcnvxf,sgl,dbl\tA1,A1\n", }, + +/* convert (u)long (in register) to double */ +{ SCONV, INDBL, + SHLL, TLL, + SHDBL, TDOUBLE|TLDOUBLE, + NDREG, RESC1, + "\tldo\t8(%sp),%sp\n" + "\tstw\tAL,-8(%sp)\n" + "\tstw\tUL,-4(%sp)\n" + "\tfldds,mb\t-8(%sp),A1\n" + "\tfcnvxf,dbl,dbl\tA1,A1\n", }, + +/* convert char to (unsigned) short/int. */ +{ SCONV, ININT, + SAREG, TCHAR, + SAREG, THWORD|TWORD, + NASL|NAREG, RESC1, + "\textrs\tAL,31,8,A1\n", }, + +/* convert unsigned char to (unsigned) short/int. */ +{ SCONV, ININT, + SAREG, TUCHAR, + SAREG, THWORD|TWORD, + NASL|NAREG, RESC1, + "\textru\tAL,31,8,A1\n", }, + +/* convert char to (unsigned) long long. */ +{ SCONV, INLL, + SAREG, TCHAR, + SBREG, TLL, + NBSL|NBREG, RESC1, + "\textrs\tAL,31,8,A1\n\textrs\tA1,0,1,U1", }, + +/* convert unsigned char to (unsigned) long long. */ +{ SCONV, INLL, + SAREG, TUCHAR, + SBREG, TLL, + NBSL|NBREG, RESC1, + "\textru\tAL,31,8,A1\n\tcopy\t%r0,U1", }, + +/* convert short to (unsigned) int. */ +{ SCONV, ININT, + SAREG, TSHORT, + SAREG, TWORD, + NASL|NAREG, RESC1, + "\textrs\tAL,31,16,A1\n", }, + +/* convert unsigned short to (unsigned) int. */ +{ SCONV, ININT, + SAREG, TUSHORT, + SAREG, THWORD, + NASL|NAREG, RESC1, + "\textru\tAL,31,16,A1\n", }, + +/* convert short to (unsigned) long long. */ +{ SCONV, INLL, + SAREG, TSHORT, + SBREG, TLL, + NBSL|NBREG, RESC1, + "\textrs\tAL,31,16,A1\n\textrs\tA1,0,1,U1", }, + +/* convert unsigned short to (unsigned) long long. */ +{ SCONV, INLL, + SAREG, TUSHORT, + SBREG, TLL, + NBSL|NBREG, RESC1, + "\textru\tAL,31,16,A1\n\tcopy\t%r0,U1", }, + +/* convert int,short,char (in memory) to int,short,char */ +{ SCONV, ININT, + SOREG, TBYTE, + SHINT, TBYTE|TPOINT, + NAREG|NASL, RESC1, + "\tldb\tAL,A1\n", }, + +{ SCONV, ININT, + SOREG, THWORD, + SHINT, THWORD|TPOINT, + NAREG|NASL, RESC1, + "\tldh\tAL,A1\n", }, + +{ SCONV, ININT, + SOREG, TWORD, + SHINT, TWORD|TPOINT, + NAREG|NASL, RESC1, + "\tldw\tAL,A1\n", }, + +/* convert (u)long long (in register) to int,short,char */ +{ SCONV, ININT, + SHLL, TLL, + SHINT, ANYFIXED, + NAREG|NASL, RESC1, + "\tcopy\tAL,A1\n", }, + +/* convert (u)long (in memory) to int,short,char */ +{ SCONV, ININT, + SOREG, TLL, + SHINT, ANYFIXED, + NAREG|NASL, RESC1, + "\tldw\tAL,A1\n", }, + +/* convert float (in register) to (u)int */ +{ SCONV, ININT, + SHFL, TFLOAT, + SHINT, TWORD, + NAREG, RESC1, + "\tfcnvfxt,sgl,sgl\tAL,AL\n" + "\tfstws,ma\tAL,4(%sp)\n" + "\tldw,mb\t-4(%sp),A1\n", }, + +/* convert double (in register) to (u)int */ +{ SCONV, ININT, + SHDBL, TDOUBLE|TLDOUBLE, + SHINT, TWORD, + NCREG|NCSL|NAREG, RESC2, + "\tfcnvfxt,dbl,sgl\tAL,A1\n" + "\tfstws,ma\tA1,4(%sp)\n" + "\tldw,mb\t-4(%sp),A2\n", }, + +/* convert float (in register) to (u)long */ +{ SCONV, INLL, + SHFL, TFLOAT, + SHLL, TLL, + NDREG|NDSL|NBREG, RESC2, + "\tfcnvfxt,sgl,dbl\tAL,A1\n" + "\tfstds,ma\tA1,8(%sp)\n" + "\tldw\t-8(%sp),A2\n" + "\tldw\t-4(%sp),U2\n" + "\tldo\t-8(%sp),%sp)\n", }, + +/* convert double (in register) to (u)long */ +{ SCONV, INLL, + SHDBL, TDOUBLE|TLDOUBLE, + SHLL, TLL, + NBREG, RESC1, + "\tfcnvfxt,dbl,dbl\tAL,AL\n" + "\tfstds,ma\tAL,8(%sp)\n" + "\tldw\t-8(%sp),A1\n" + "\tldw\t-4(%sp),U1\n" + "\tldo\t-8(%sp),%sp)\n", }, + +/* + * Subroutine calls. + */ + +{ CALL, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, 0, + "ZP\tblr\t%r0, %rp\n" + "\tbv,n\t%r0(AL)\n" + "\tnop\nZC", }, + +{ UCALL, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, 0, + "ZP\tblr\t%r0, %rp\n" + "\tbv,n\t%r0(AL)\n" + "\tnop\nZC", }, + +{ CALL, ININT, + SAREG, TANY, + SHINT, ANYFIXED|TPOINT, + NAREG|NASL, RESC1, + "ZP\tblr\t%r0, %rp\n" + "\tbv,n\t%r0(AL)\n" + "\tnop\nZC", }, + +{ UCALL, ININT, + SAREG, TANY, + SHINT, ANYFIXED|TPOINT, + NAREG|NASL, RESC1, + "ZP\tblr\t%r0, %rp\n" + "\tbv,n\t%r0(AL)\n" + "\tnop\nZC", }, + +{ CALL, INLL, + SAREG, TANY, + SHLL, TLL, + NBREG|NBSL, RESC1, + "ZP\tblr\t%r0, %rp\n" + "\tbv,n\t%r0(AL)\n" + "\tnop\nZC", }, + +{ UCALL, INLL, + SAREG, TANY, + SHLL, TLL, + NBREG|NBSL, RESC1, + "ZP\tblr\t%r0, %rp\n" + "\tbv,n\t%r0(AL)\n" + "\tnop\nZC", }, + +{ CALL, INFL, + SAREG, TANY, + SHFL, TFLOAT, + NCREG|NCSL, RESC1, + "ZP\tblr\t%r0, %rp\n" + "\tbv,n\t%r0(AL)\n" + "\tnop\nZC", }, + +{ UCALL, INFL, + SAREG, TANY, + SHFL, TFLOAT, + NCREG|NCSL, RESC1, + "ZP\tblr\t%r0, %rp\n" + "\tbv,n\t%r0(AL)\n" + "\tnop\nZC", }, + +{ CALL, INDBL, + SAREG, TANY, + SHDBL, TDOUBLE|TLDOUBLE, + NDREG|NDSL, RESC1, + "ZP\tblr\t%r0, %rp\n" + "\tbv,n\t%r0(AL)\n" + "\tnop\nZC", }, + +{ UCALL, INDBL, + SAREG, TANY, + SHDBL, TDOUBLE|TLDOUBLE, + NDREG|NDSL, RESC1, + "ZP\tblr\t%r0, %rp\n" + "\tbv,n\t%r0(AL)\n" + "\tnop\nZC", }, + +/* + * The next rules handle all binop-style operators. + */ +/* TODO fix char/short overflows */ + +{ PLUS, INLL, + SHLL, TLL, + SPICON, TANY, + NBREG|NBSL, RESC1, + "\taddi\tAL,AR,A1\n" + "\taddc\tUL,%r0,U1\n", }, + +{ PLUS, INLL, + SHLL, TLL, + SHLL, TLL, + NBREG|NBSL|NBSR, RESC1, + "\tadd\tAL,AR,A1\n" + "\taddc\tUL,UR,U1\n", }, + +{ PLUS, INFL, + SHFL, TFLOAT, + SHFL, TFLOAT, + NCREG|NCSL|NCSR, RESC1, + "\tfadd,sgl\tAL,AR,A1\n", }, + +{ PLUS, INDBL, + SHDBL, TDOUBLE|TLDOUBLE, + SHDBL, TDOUBLE|TLDOUBLE, + NDREG|NDSL|NDSR, RESC1, + "\tfadd,dbl\tAL,AR,A1\n", }, + +{ PLUS, ININT, + SHINT, ANYFIXED|TPOINT, + SONE, TANY, + NAREG|NASL, RESC1, + "\tldo\t1(AL),A1\n", }, + +{ PLUS, ININT, + SHINT, ANYFIXED|TPOINT, + SPCON, TANY, + NAREG|NASL, RESC1, + "\tldo\tCR(AL),A1\n", }, + +{ MINUS, INLL, + SHLL, TLL, + SPICON, TANY, + NBREG|NBSL|NBSR, RESC1, + "\tsubi\tAL,AR,A1\n" + "\tsubb\tUL,%r0,U1\n", }, + +{ PLUS, ININT, + SHINT, TANY|TPOINT, + SPNAME, TANY, + NAREG|NASL, RESC1, + "\tldo\tAR(AL),A1\n", }, + +{ MINUS, INLL, + SHLL, TLL, + SHLL, TLL, + NBREG|NBSL|NBSR, RESC1, + "\tsub\tAL,AR,A1\n" + "\tsubb\tUL,UR,U1\n", }, + +{ MINUS, INFL, + SHFL, TFLOAT, + SHFL, TFLOAT, + NCREG|NCSL|NCSR, RESC1, + "\tfsub,sgl\tAL,AR,A1\n", }, + +{ MINUS, INDBL, + SHDBL, TDOUBLE|TLDOUBLE, + SHDBL, TDOUBLE|TLDOUBLE, + NDREG|NDSL|NDSR, RESC1, + "\tfsub,dbl\tAL,AR,A1\n", }, + +{ MINUS, ININT, + SHINT, ANYFIXED|TPOINT, + SONE, TANY, + NAREG|NASL, RESC1, + "\tldo\t-1(AL),A1\n", }, + +{ MINUS, ININT, + SHINT, ANYFIXED|TPOINT, + SPCON, TANY, + NAREG|NASL, RESC1, + "\tldo\t-CR(AL),A1\n", }, + +/* Simple reg->reg ops */ +{ OPSIMP, ININT, + SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + NAREG|NASL, RESC1, + "\tO\tAL,AR,A1\n", }, + +{ OPSIMP, INLL, + SHLL, TLL, + SHLL, TLL, + NBREG|NBSL|NBSR, RESC1, + "\tO\tAL,AR,A1\n" + "\tO\tUL,UR,U1\n", }, + +/* + * The next rules handle all shift operators. + */ +{ LS, ININT, + SHINT, ANYFIXED, + SCON, ANYFIXED, + NAREG|NASL, RESC1, + "\tzdep\tAL,31-AR,32-AR,A1\n", }, + +{ LS, ININT, + SHINT, ANYFIXED, + SHINT, ANYFIXED, + NAREG|NASR, RESC1, + "\tsubi\t31,AR,A1\n" + "\tmtsar\tA1\n" + "\tzvdep\tAL,32,A1\n", }, + +{ RS, INLL, + SHLL, TLONGLONG, + SCON, ANYFIXED, + NBREG|NBSL, RESC1, + "\tshd\tUL,AL,31-AR,A1\n" + "\textrs\tUL,31-AR,32,U1\n", }, + +{ RS, INLL, + SHLL, TULONGLONG, + SCON, ANYFIXED, + NBREG|NBSL, RESC1, + "\tshd\tUL,AL,AR,A1\n" + "\textru\tUL,31-AR,32,U1\n", }, + +{ RS, ININT, + SHINT, ANYSIGNED, + SCON, ANYFIXED, + NAREG|NASL, RESC1, + "\textrs\tAL,31-AR,32,A1\n", }, + +{ RS, ININT, + SHINT, ANYUSIGNED, + SCON, ANYFIXED, + NAREG|NASL, RESC1, + "\textru\tAL,31-AR,32,A1\n", }, + +/* TODO the following should be split into mtsar and actual shift parts */ +{ RS, ININT, + SHINT, ANYSIGNED, + SHINT, ANYFIXED, + NAREG|NASR, RESC1, + "\tsubi\t31,AR,A1\n" + "\tmtsar\tA1\n" + "\tvextrs\tAL,32,A1\n", }, + +{ RS, ININT, + SHINT, ANYUSIGNED, + SHINT, ANYFIXED, + NAREG|NASR, RESC1, + "\tsubi\t31,AR,A1\n" + "\tmtsar\tA1\n" + "\tvextru\tAL,32,A1\n", }, + +/* + * The next rules takes care of assignments. "=". + */ + +{ ASSIGN, FOREFF|INAREG, + SAREG, TWORD|TPOINT, + SPCON, TANY, + 0, RDEST, + "\tldi\tAR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SOREG, TBYTE, + SHINT, TBYTE, + 0, RDEST, + "\tstb\tAR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SOREG, THWORD, + SHINT, THWORD, + 0, RDEST, + "\tsth\tAR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SOREG, TWORD|TPOINT, + SHINT, TWORD|TPOINT, + 0, RDEST, + "\tstw\tAR,AL\n", }, + +{ ASSIGN, FOREFF|INLL, + SOREG, TLL, + SHLL, TLL, + 0, RDEST, + "\tstw\tAR,AL\n" + "\tstw\tUR,UL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SHINT, TBYTE, + SOREG, TBYTE, + 0, RDEST, + "\tldb\tAR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SHINT, THWORD, + SOREG, THWORD, + 0, RDEST, + "\tldh\tAR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SHINT, TWORD|TPOINT, + SOREG, TWORD|TPOINT, + 0, RDEST, + "\tldw\tAR,AL\n", }, + +{ ASSIGN, FOREFF|INLL, + SHLL, TLL, + SOREG, TLL, + 0, RDEST, + "\tldw\tAR,AL\n" + "\tldw\tUR,UL\n", }, + +{ ASSIGN, FOREFF|ININT, + SHINT, TWORD|TPOINT, + SHINT, TWORD|TPOINT, + 0, RDEST, + "\tcopy\tAR,AL\n", }, + +{ ASSIGN, FOREFF|ININT, + SHINT, ANYFIXED, + SHINT, ANYFIXED, + 0, RDEST, + "\tcopy\tAR,AL\n", }, + +{ ASSIGN, FOREFF|ININT, + SFLD, TANY, + SPIMM, TANY, + 0, RDEST, + "\tdepi\tAR,31-H,S,AL\n", }, + +{ ASSIGN, FOREFF|ININT, + SFLD, TANY, + SHINT, TANY, + 0, RDEST, + "\tdep\tAR,31-H,S,AL\n", }, + +{ ASSIGN, FOREFF|INLL, + SHLL, TLL, + SHLL, TLL, + 0, RDEST, + "\tcopy\tAR,AL\n" + "\tcopy\tUR,UL\n", }, + +{ ASSIGN, FOREFF|INFL, + SHFL, TFLOAT, + SHFL, TFLOAT, + 0, RDEST, + "\tfcpy,sgl\tAR,AL\n", }, + +{ ASSIGN, FOREFF|INDBL, + SHDBL, TDOUBLE|TLDOUBLE, + SHDBL, TDOUBLE|TLDOUBLE, + 0, RDEST, + "\tfcpy,dbl\tAR,AL\n", }, + +{ ASSIGN, FOREFF|INFL, + SHFL, TFLOAT, + SOREG, TFLOAT, + 0, RDEST, + "\tfldws\tAR,AL\n", }, + +{ ASSIGN, FOREFF|INDBL, + SHDBL, TDOUBLE|TLDOUBLE, + SOREG, TDOUBLE|TLDOUBLE, + 0, RDEST, + "\tfldds\tAR,AL\n", }, + +{ ASSIGN, FOREFF|INFL, + SOREG, TFLOAT, + SHFL, TFLOAT, + 0, RDEST, + "\tfstws\tAR,AL\n", }, + +{ ASSIGN, FOREFF|INDBL, + SOREG, TDOUBLE|TLDOUBLE, + SHDBL, TDOUBLE|TLDOUBLE, + 0, RDEST, + "\tfstds\tAR,AL\n", }, + +/* + * DIV/MOD/MUL + */ +{ DIV, INFL, + SHFL, TFLOAT, + SHFL, TFLOAT, + NCREG|NCSL|NCSR, RESC1, + "\tfdiv,sgl\tAL,AR,A1\n", }, + +{ DIV, INDBL, + SHDBL, TDOUBLE|TLDOUBLE, + SHDBL, TDOUBLE|TLDOUBLE, + NDREG|NDSL|NDSR, RESC1, + "\tfdiv,dbl\tAL,AR,A1\n", }, + +{ MUL, INFL, + SHFL, TFLOAT, + SHFL, TFLOAT, + NCREG|NCSL|NCSR, RESC1, + "\tfmul,sgl\tAL,AR,A1\n", }, + +{ MUL, INDBL, + SHDBL, TDOUBLE|TLDOUBLE, + SHDBL, TDOUBLE|TLDOUBLE, + NDREG|NDSL|NDSR, RESC1, + "\tfmul,dbl\tAL,AR,A1\n", }, + +/* + * Indirection operators. + */ +{ UMUL, INLL, + SANY, TANY, + SOREG, TLL, + NBREG, RESC1, + "\tldw\tAL,A1\n" + "\tldw\tUL,U1\n", }, + +{ UMUL, ININT, + SANY, TPOINT|TWORD, + SOREG, TPOINT|TWORD, + NAREG|NASL, RESC1, + "\tldw\tAL,A1\n", }, + +{ UMUL, ININT, + SANY, TANY, + SOREG, THWORD, + NAREG|NASL, RESC1, + "\tldh\tAL,A1\n", }, + +{ UMUL, ININT, + SANY, TANY, + SOREG, TBYTE, + NAREG|NASL, RESC1, + "\tldb\tAL,A1\n", }, + +{ UMUL, INDBL, + SANY, TANY, + SOREG, TDOUBLE|TLDOUBLE, + NDREG|NDSL, RESC1, + "\tfldds\tAL,A1\n", }, + +{ UMUL, INFL, + SANY, TANY, + SOREG, TFLOAT, + NCREG|NCSL, RESC1, + "\tfldws\tAL,A1\n", }, + +/* + * Logical/branching operators + */ +{ OPLOG, FORCC, + SHLL, TLL, + SHLL, TLL, + 0, 0, + "ZD", }, + +{ OPLOG, FORCC, + SHINT, ANYFIXED|TPOINT, + SPIMM, ANYFIXED|TPOINT, + 0, 0, + "\tcomib,O\tAR,AL,LC\n\tnop\n", }, + +{ OPLOG, FORCC, + SHINT, ANYFIXED|TPOINT, + SHINT, ANYFIXED|TPOINT, + 0, 0, + "\tcomb,O\tAR,AL,LC\n\tnop\n", }, + +{ OPLOG, FORCC, + SHFL, TFLOAT, + SHFL, TFLOAT, + 0, RESCC, + "\tfcmp,sgl,!O\tAR,AL\n" + "\tftest\n" + "\tb\tLC\n" + "\tnop", }, + +{ OPLOG, FORCC, + SHDBL, TDOUBLE|TLDOUBLE, + SHDBL, TDOUBLE|TLDOUBLE, + 0, RESCC, + "\tfcmp,dbl,!O\tAR,AL\n" + "\tftest\n" + "\tb\tLC\n" + "\tnop", }, + +/* + * Jumps. + */ +{ GOTO, FOREFF, + SCON, TANY, + SANY, TANY, + 0, RNOP, + "\tb\tLL\n\tnop\n", }, + +#ifdef GCC_COMPAT +{ GOTO, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, RNOP, + "\tbv\t%r0(AL)\n\tnop\n", }, +#endif + + +/* + * Convert LTYPE to reg. + */ + +{ OPLTYPE, INAREG, + SAREG, TANY, + SNAME, TANY, + 0, RDEST, + "\taddil\tUR,%r27\n", }, + +{ OPLTYPE, INAREG, + SAREG, TANY, + SCON, TPOINT, + 0, RDEST, + "\taddil\tUR,%r27\n", }, + +{ OPLTYPE, INLL, + SANY, TANY, + SOREG, TLL, + NBREG|NBSL, RESC1, + "\tldw\tAL,A1\n" + "\tldw\tUL,U1\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SOREG, TWORD|TPOINT, + NAREG|NASL, RESC1, + "\tldw\tAL,A1\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SAREG, TWORD|TPOINT, + NAREG|NASL, RESC1, + "\tcopy\tAL,A1\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SPCNHI, ANYFIXED, + NAREG, RESC1, + "\tldil\tUR,A1\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SPCON, ANYFIXED, + NAREG, RESC1, + "\tldi\tAR,A1\n", }, + +{ OPLTYPE, INLL, + SANY, TANY, + SPCON, TLL, + NBREG, RESC1, + "\tldi\tAR,A1\n" + "\tcopy\t%r0,U1\n", }, + +{ OPLTYPE, ININT, + SANY, TANY, + SCON, TWORD, + NAREG, RESC1, + "\tldil\tUR,A1\n" + "\tldo\tAR(A1),A1\n", }, + +{ OPLTYPE, INLL, + SHLL, TLL, + SPCNHW, TLL, + NBREG, RESC1, + "\tldil\tUR>>32,U1\n" + "\tldo\tAR>>32(U1),U1\n" + "\tcopy\t%r0,A1\n", }, + +{ OPLTYPE, INLL, + SHLL, TLL, + SPCNLW, TLL, + NBREG, RESC1, + "\tcopy\t%r0,U1\n" + "\tldil\tUR,A1\n" + "\tldo\tAR(A1),A1\n", }, + +{ OPLTYPE, INLL, + SHLL, TLL, + SCON, TLL, + NBREG, RESC1, + "\tldil\tUR,A1\n" + "\tldo\tAR(A1),A1\n" + "\tldil\tUR>>32,U1\n" + "\tldo\tAR>>32(U1),U1\n", }, + +{ OPLTYPE, INCREG, + SANY, TFLOAT, + SHFL, TFLOAT, + NCREG, RESC1, + "\tfldws\tAL,A1\n", }, + +{ OPLTYPE, INDREG, + SANY, TDOUBLE|TLDOUBLE, + SHDBL, TDOUBLE|TLDOUBLE, + NDREG, RESC1, + "\tfldds\tAL,A1\n", }, + +/* + * Negate a word. + */ +{ UMINUS, INLL, + SHLL, TLL, + SHLL, TLL, + NBREG|NBSL, RESC1, + "\tsub\t%r0,AL,A1\n" + "\tsubb\t%r0,UL,A1\n", }, + +{ UMINUS, ININT, + SHINT, TWORD, + SHINT, TWORD, + NAREG|NASL, RESC1, + "\tsub\t%r0,AL,A1\n", }, + +{ UMINUS, INFL, + SHFL, TFLOAT, + SHFL, TFLOAT, + NCREG|NCSL, RESC1, + "\tfsub,sgl\t%fr0,AL,A1\n", }, + +{ UMINUS, INDBL, + SHDBL, TDOUBLE|TLDOUBLE, + SHDBL, TDOUBLE|TLDOUBLE, + NDREG|NDSL, RESC1, + "\tfsub,dbl\t%fr0,AL,A1\n", }, + +{ COMPL, INLL, + SHLL, TLL, + SANY, TANY, + NBREG|NBSL, RESC1, + "\tuaddcm\t%r0,AL,A1\n" + "\tuaddcm\t%r0,UL,U1\n", }, + +{ COMPL, ININT, + SHINT, ANYFIXED, + SANY, TANY, + NAREG|NASL, RESC1, + "\tuaddcm\t%r0,AL,A1\n", }, + +/* + * Arguments to functions. + */ + +{ STARG, FOREFF, + SAREG|SOREG|SNAME|SCON, TANY, + SANY, TSTRUCT, + NAREG | RNULL, 0, + "ZS", }, + +/* + * struct field ops + */ +{ FLD, ININT, + SHINT, TANY, + SFLD, ANYSIGNED, + NAREG|NASL, RESC1, + "\textrs\tAL,31-H,S,A1\n", }, + +{ FLD, ININT, + SHINT, TANY, + SFLD, ANYUSIGNED, + NAREG|NASL, RESC1, + "\textru\tAL,31-H,S,A1\n", }, + +# define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,"" + +{ UMUL, DF( UMUL ), }, + +{ ASSIGN, DF(ASSIGN), }, + +{ STASG, DF(STASG), }, + +{ FLD, DF(FLD), }, + +{ OPLEAF, DF(NAME), }, + +/* { INIT, DF(INIT), }, */ + +{ OPUNARY, DF(UMINUS), }, + +{ OPANY, DF(BITYPE), }, + +{ FREE, FREE, + FREE, FREE, + FREE, FREE, + FREE, FREE, + "HELP; I'm in trouble\n" }, +}; + +int tablesize = sizeof(table)/sizeof(table[0]); diff --git a/compilers/pcc/pcc-1.0.0/arch/i386/CVS/Entries b/compilers/pcc/pcc-1.0.0/arch/i386/CVS/Entries new file mode 100644 index 00000000..228c473d --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/i386/CVS/Entries @@ -0,0 +1,8 @@ +/code.c/1.56.2.1/Tue Mar 1 17:33:24 2011//Tr-1-0-0-RELEASE +/flocal.c/1.16/Fri Dec 19 20:26:50 2008//Tr-1-0-0-RELEASE +/local.c/1.130.2.3/Wed Mar 30 16:35:36 2011//Tr-1-0-0-RELEASE +/local2.c/1.154.2.2/Sat Feb 26 07:17:34 2011//Tr-1-0-0-RELEASE +/macdefs.h/1.77/Fri Feb 4 15:08:58 2011//Tr-1-0-0-RELEASE +/order.c/1.59/Sat Jan 29 09:55:29 2011//Tr-1-0-0-RELEASE +/table.c/1.128/Sat Jan 29 09:55:29 2011//Tr-1-0-0-RELEASE +D diff --git a/compilers/pcc/pcc-1.0.0/arch/i386/CVS/Repository b/compilers/pcc/pcc-1.0.0/arch/i386/CVS/Repository new file mode 100644 index 00000000..8bae03dc --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/i386/CVS/Repository @@ -0,0 +1 @@ +pcc/arch/i386 diff --git a/compilers/pcc/pcc-1.0.0/arch/i386/CVS/Root b/compilers/pcc/pcc-1.0.0/arch/i386/CVS/Root new file mode 100644 index 00000000..71e2ccb9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/i386/CVS/Root @@ -0,0 +1 @@ +/cvsroot diff --git a/compilers/pcc/pcc-1.0.0/arch/i386/CVS/Tag b/compilers/pcc/pcc-1.0.0/arch/i386/CVS/Tag new file mode 100644 index 00000000..060fac05 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/i386/CVS/Tag @@ -0,0 +1 @@ +Nr-1-0-0-RELEASE diff --git a/compilers/pcc/pcc-1.0.0/arch/i386/code.c b/compilers/pcc/pcc-1.0.0/arch/i386/code.c new file mode 100644 index 00000000..c891c1ca --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/i386/code.c @@ -0,0 +1,431 @@ +/* $Id: code.c,v 1.56.2.1 2011/03/01 17:33:24 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass1.h" + +int lastloc = -1; + +/* + * Define everything needed to print out some data (or text). + * This means segment, alignment, visibility, etc. + */ +void +defloc(struct symtab *sp) +{ + extern char *nextsect; + struct attr *ap; + int weak = 0; + char *name = NULL; +#if defined(ELFABI) || defined(PECOFFABI) + static char *loctbl[] = { "text", "data", "section .rodata" }; +#elif defined(MACHOABI) + static char *loctbl[] = { "text", "data", "const_data" }; +#endif + TWORD t; + int s, al; + + if (sp == NULL) { + lastloc = -1; + return; + } + t = sp->stype; + s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA; + if ((name = sp->soname) == NULL) + name = exname(sp->sname); +#ifdef TLS + if (sp->sflags & STLS) { + if (s != DATA) + cerror("non-data symbol in tls section"); + nextsect = ".tdata"; + } +#endif +#ifdef GCC_COMPAT + { + if ((ap = attr_find(sp->sap, GCC_ATYP_SECTION)) != NULL) + nextsect = ap->sarg(0); + if (attr_find(sp->sap, GCC_ATYP_WEAK) != NULL) + weak = 1; + if (attr_find(sp->sap, GCC_ATYP_DESTRUCTOR)) { + printf("\t.section\t.dtors,\"aw\",@progbits\n"); + printf("\t.align 4\n\t.long\t%s\n", name); + lastloc = -1; + } + if (attr_find(sp->sap, GCC_ATYP_CONSTRUCTOR)) { + printf("\t.section\t.ctors,\"aw\",@progbits\n"); + printf("\t.align 4\n\t.long\t%s\n", name); + lastloc = -1; + } + if ((ap = attr_find(sp->sap, GCC_ATYP_VISIBILITY)) && + strcmp(ap->sarg(0), "default")) + printf("\t.%s %s\n", ap->sarg(0), name); + } +#endif +#ifdef ELFABI + if (kflag && !ISFTN(t)) { + /* Must place aggregates with pointers in relocatable memory */ + TWORD t2 = t; + + while (ISARY(t2)) + t2 = DECREF(t2); + if (t2 > LDOUBLE) { + /* put in reloc memory */ + printf("\t.section .data.rel.local,\"aw\",@progbits\n"); + s = lastloc = -1; + } + } +#endif + if (nextsect) { + printf(" .section %s,\"wa\",@progbits\n", nextsect); + nextsect = NULL; + s = -1; + } else if (s != lastloc) + printf(" .%s\n", loctbl[s]); + lastloc = s; + while (ISARY(t)) + t = DECREF(t); + al = ISFTN(t) ? ALINT : talign(t, sp->sap); + if (al > ALCHAR) + printf(" .align %d\n", al/ALCHAR); + if (weak) + printf(" .weak %s\n", name); + else if (sp->sclass == EXTDEF) { + printf(" .globl %s\n", name); +#if defined(ELFABI) + printf("\t.type %s,@%s\n", name, + ISFTN(t)? "function" : "object"); +#endif + } +#if defined(ELFABI) + if (!ISFTN(t)) { + if (sp->slevel == 0) + printf("\t.size %s,%d\n", name, + (int)tsize(t, sp->sdf, sp->sap)/SZCHAR); + else + printf("\t.size " LABFMT ",%d\n", sp->soffset, + (int)tsize(t, sp->sdf, sp->sap)/SZCHAR); + } +#endif + if (sp->slevel == 0) + printf("%s:\n", name); + else + printf(LABFMT ":\n", sp->soffset); +} + +/* + * code for the end of a function + * deals with struct return here + */ +void +efcode() +{ + extern int gotnr; + NODE *p, *q; + + gotnr = 0; /* new number for next fun */ + if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) + return; +#if defined(os_openbsd) + /* struct return for small structs */ + int sz = tsize(BTYPE(cftnsp->stype), cftnsp->sdf, cftnsp->sap); + if (sz == SZCHAR || sz == SZSHORT || sz == SZINT || sz == SZLONGLONG) { + /* Pointer to struct in eax */ + if (sz == SZLONGLONG) { + q = block(OREG, NIL, NIL, INT, 0, MKAP(INT)); + q->n_lval = 4; + p = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + p->n_rval = EDX; + ecomp(buildtree(ASSIGN, p, q)); + } + if (sz < SZSHORT) sz = CHAR; + else if (sz > SZSHORT) sz = INT; + else sz = SHORT; + q = block(OREG, NIL, NIL, sz, 0, MKAP(sz)); + p = block(REG, NIL, NIL, sz, 0, MKAP(sz)); + ecomp(buildtree(ASSIGN, p, q)); + return; + } +#endif + /* Create struct assignment */ + q = block(OREG, NIL, NIL, PTR+STRTY, 0, cftnsp->sap); + q->n_rval = EBP; + q->n_lval = 8; /* return buffer offset */ + q = buildtree(UMUL, q, NIL); + p = block(REG, NIL, NIL, PTR+STRTY, 0, cftnsp->sap); + p = buildtree(UMUL, p, NIL); + p = buildtree(ASSIGN, q, p); + ecomp(p); + + /* put hidden arg in eax on return */ + q = block(OREG, NIL, NIL, INT, 0, MKAP(INT)); + regno(q) = FPREG; + q->n_lval = 8; + p = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + regno(p) = EAX; + ecomp(buildtree(ASSIGN, p, q)); +} + +/* + * code for the beginning of a function; a is an array of + * indices in symtab for the arguments; n is the number + */ +void +bfcode(struct symtab **sp, int cnt) +{ + extern int argstacksize; + struct symtab *sp2; + extern int gotnr; + NODE *n, *p; + int i; + + if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) { + /* Function returns struct, adjust arg offset */ +#if defined(os_openbsd) + /* OpenBSD uses non-standard return for small structs */ + int sz = tsize(BTYPE(cftnsp->stype), cftnsp->sdf, cftnsp->sap); + if (sz != SZCHAR && sz != SZSHORT && + sz != SZINT && sz != SZLONGLONG) +#endif + for (i = 0; i < cnt; i++) + sp[i]->soffset += SZPOINT(INT); + } + +#ifdef GCC_COMPAT + if (attr_find(cftnsp->sap, GCC_ATYP_STDCALL) != NULL) + cftnsp->sflags |= SSTDCALL; +#endif + + /* + * Count the arguments + */ + argstacksize = 0; + if (cftnsp->sflags & SSTDCALL) { +#ifdef os_win32 + + char buf[256]; + char *name; +#endif + + for (i = 0; i < cnt; i++) { + TWORD t = sp[i]->stype; + if (t == STRTY || t == UNIONTY) + argstacksize += + tsize(t, sp[i]->sdf, sp[i]->sap); + else + argstacksize += szty(t) * SZINT / SZCHAR; + } +#ifdef os_win32 + /* + * mangle name in symbol table as a callee. + */ + if ((name = cftnsp->soname) == NULL) + name = exname(cftnsp->sname); + snprintf(buf, 256, "%s@%d", name, argstacksize); + cftnsp->soname = addname(buf); +#endif + } + + if (kflag) { +#define STL 200 + char *str = inlalloc(STL); +#if !defined(MACHOABI) + int l = getlab(); +#else + char *name; +#endif + + /* Generate extended assembler for PIC prolog */ + p = tempnode(0, INT, 0, MKAP(INT)); + gotnr = regno(p); + p = block(XARG, p, NIL, INT, 0, MKAP(INT)); + p->n_name = "=g"; + p = block(XASM, p, bcon(0), INT, 0, MKAP(INT)); + +#if defined(MACHOABI) + if ((name = cftnsp->soname) == NULL) + name = cftnsp->sname; + if (snprintf(str, STL, "call L%s$pb\nL%s$pb:\n\tpopl %%0\n", + name, name) >= STL) + cerror("bfcode"); +#else + if (snprintf(str, STL, + "call " LABFMT "\n" LABFMT ":\n popl %%0\n" + " addl $_GLOBAL_OFFSET_TABLE_+[.-" LABFMT "], %%0\n", + l, l, l) >= STL) + cerror("bfcode"); +#endif + p->n_name = str; + p->n_right->n_type = STRTY; + ecomp(p); + } + if (xtemps == 0) + return; + + /* put arguments in temporaries */ + for (i = 0; i < cnt; i++) { + if (sp[i]->stype == STRTY || sp[i]->stype == UNIONTY || + cisreg(sp[i]->stype) == 0) + continue; + if (cqual(sp[i]->stype, sp[i]->squal) & VOL) + continue; + sp2 = sp[i]; + n = tempnode(0, sp[i]->stype, sp[i]->sdf, sp[i]->sap); + n = buildtree(ASSIGN, n, nametree(sp2)); + sp[i]->soffset = regno(n->n_left); + sp[i]->sflags |= STNODE; + ecomp(n); + } +} + + +/* + * by now, the automatics and register variables are allocated + */ +void +bccode() +{ + SETOFF(autooff, SZINT); +} + +#if defined(MACHOABI) +struct stub stublist; +struct stub nlplist; +#endif + +/* called just before final exit */ +/* flag is 1 if errors, 0 if none */ +void +ejobcode(int flag ) +{ +#if defined(MACHOABI) + /* + * iterate over the stublist and output the PIC stubs +` */ + if (kflag) { + struct stub *p; + + DLIST_FOREACH(p, &stublist, link) { + printf("\t.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5\n"); + printf("L%s$stub:\n", p->name); + printf("\t.indirect_symbol %s\n", p->name); + printf("\thlt ; hlt ; hlt ; hlt ; hlt\n"); + printf("\t.subsections_via_symbols\n"); + } + + printf("\t.section __IMPORT,__pointers,non_lazy_symbol_pointers\n"); + DLIST_FOREACH(p, &nlplist, link) { + printf("L%s$non_lazy_ptr:\n", p->name); + printf("\t.indirect_symbol %s\n", p->name); + printf("\t.long 0\n"); + } + + } +#endif + +#define _MKSTR(x) #x +#define MKSTR(x) _MKSTR(x) +#define OS MKSTR(TARGOS) + printf("\t.ident \"PCC: %s (%s)\"\n", PACKAGE_STRING, OS); +} + +void +bjobcode() +{ +#if defined(MACHOABI) + DLIST_INIT(&stublist, link); + DLIST_INIT(&nlplist, link); +#endif +} + +/* + * Called with a function call with arguments as argument. + * This is done early in buildtree() and only done once. + * Returns p. + */ +NODE * +funcode(NODE *p) +{ + extern int gotnr; + NODE *r, *l; + + /* Fix function call arguments. On x86, just add funarg */ + for (r = p->n_right; r->n_op == CM; r = r->n_left) { + if (r->n_right->n_op != STARG) + r->n_right = block(FUNARG, r->n_right, NIL, + r->n_right->n_type, r->n_right->n_df, + r->n_right->n_ap); + } + if (r->n_op != STARG) { + l = talloc(); + *l = *r; + r->n_op = FUNARG; + r->n_left = l; + r->n_type = l->n_type; + } + if (kflag == 0) + return p; +#if defined(ELFABI) + /* Create an ASSIGN node for ebx */ + l = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + l->n_rval = EBX; + l = buildtree(ASSIGN, l, tempnode(gotnr, INT, 0, MKAP(INT))); + if (p->n_right->n_op != CM) { + p->n_right = block(CM, l, p->n_right, INT, 0, MKAP(INT)); + } else { + for (r = p->n_right; r->n_left->n_op == CM; r = r->n_left) + ; + r->n_left = block(CM, l, r->n_left, INT, 0, MKAP(INT)); + } +#endif + return p; +} + +/* + * return the alignment of field of type t + */ +int +fldal(unsigned int t) +{ + uerror("illegal field type"); + return(ALINT); +} + +/* fix up type of field p */ +void +fldty(struct symtab *p) +{ +} + +/* + * XXX - fix genswitch. + */ +int +mygenswitch(int num, TWORD type, struct swents **p, int n) +{ + return 0; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/i386/flocal.c b/compilers/pcc/pcc-1.0.0/arch/i386/flocal.c new file mode 100644 index 00000000..0abd7139 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/i386/flocal.c @@ -0,0 +1,234 @@ +/* $Id: flocal.c,v 1.16 2008/12/19 20:26:50 ragge Exp $ */ +/* + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code and documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditionsand the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include + +#include "defines.h" +#include "defs.h" + +void +prchars(int *s) +{ + printf("\t.byte 0%o,0%o\n", s[0], s[1]); +} + + +void +setloc(int l) +{ + static int lastloc = -1; + static char *loctbl[] = + { "text", "data", "section .rodata", "section .rodata", "bss" }; + if (l == lastloc) + return; + printf("\t.%s\n", loctbl[l]); + lastloc = l; +} + +#ifdef FCOM + + +/* + PDP11-780/VAX - SPECIFIC PRINTING ROUTINES +*/ + +/* + * Called just before return from a subroutine. + */ +void +goret(int type) +{ +} + +/* + * Print out a label. + */ +void +prlabel(int k) +{ + printf(LABFMT ":\n", k); +} + +/* + * Print naming for location. + * name[0] is location type. + */ +void +prnloc(char *name) +{ + if (*name == '0') + setloc(DATA); + else + fatal("unhandled prnloc %c", *name); + printf("%s:\n", name+1); +} + +/* + * Print integer constant. + */ +void +prconi(FILE *fp, int type, ftnint n) +{ + fprintf(fp, "\t%s\t%ld\n", (type==TYSHORT ? ".word" : ".long"), n); +} + +/* + * Print address constant, given as a label number. + */ +void +prcona(ftnint a) +{ + printf("\t.long\t" LABFMT "\n", (int)a); +} + +/* + * Print out a floating constant. + */ +void +prconr(FILE *fp, int type, double x) +{ + fprintf(fp, "\t%s\t0f%e\n", (type==TYREAL ? ".float" : ".double"), x); +} + +void +preven(int k) +{ + if (k > 1) + printf("\t.align\t%d\n", k); +} + +/* + * Convert a tag and offset into the symtab table to a string. + * An external string is never longer than XL bytes. + */ +char * +memname(int stg, int mem) +{ +#define MLEN (XL + 10) + char *s = malloc(MLEN); + + switch(stg) { + case STGCOMMON: + case STGEXT: + snprintf(s, MLEN, "%s", varstr(XL, extsymtab[mem].extname)); + break; + + case STGBSS: + case STGINIT: + snprintf(s, MLEN, "v.%d", mem); + break; + + case STGCONST: + snprintf(s, MLEN, ".L%d", mem); + break; + + case STGEQUIV: + snprintf(s, MLEN, "q.%d", mem); + break; + + default: + fatal1("memname: invalid vstg %d", stg); + } + return(s); +} + +void +prlocvar(char *s, ftnint len) +{ + printf("\t.lcomm\t%s,%ld\n", s, len); +} + + +void +prext(char *name, ftnint leng, int init) +{ + if(leng == 0) + printf("\t.globl\t%s\n", name); + else + printf("\t.comm\t%s,%ld\n", name, leng); +} + +void +prendproc() +{ +} + +void +prtail() +{ +} + +void +prolog(struct entrypoint *ep, struct bigblock *argvec) +{ + /* Ignore for now. ENTRY is not supported */ +} + + + +void +prdbginfo() +{ +} + +static void +fcheck(NODE *p, void *arg) +{ + NODE *r, *l; + + switch (p->n_op) { + case CALL: /* fix arguments */ + for (r = p->n_right; r->n_op == CM; r = r->n_left) { + r->n_right = mkunode(FUNARG, r->n_right, 0, + r->n_right->n_type); + } + l = talloc(); + *l = *r; + r->n_op = FUNARG; + r->n_left = l; + r->n_type = l->n_type; + break; + } +} + +/* + * Called just before the tree is written out to pass2. + */ +void p2tree(NODE *p); +void +p2tree(NODE *p) +{ + walkf(p, fcheck, 0); +} +#endif /* FCOM */ diff --git a/compilers/pcc/pcc-1.0.0/arch/i386/local.c b/compilers/pcc/pcc-1.0.0/arch/i386/local.c new file mode 100644 index 00000000..daab318c --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/i386/local.c @@ -0,0 +1,1574 @@ +/* $Id: local.c,v 1.130.2.3 2011/03/30 16:35:36 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "pass1.h" + +/* this file contains code which is dependent on the target machine */ + +#ifdef notyet +/* + * Check if a constant is too large for a type. + */ +static int +toolarge(TWORD t, CONSZ con) +{ + U_CONSZ ucon = con; + + switch (t) { + case ULONGLONG: + case LONGLONG: + break; /* cannot be too large */ +#define SCHK(i) case i: if (con > MAX_##i || con < MIN_##i) return 1; break +#define UCHK(i) case i: if (ucon > MAX_##i) return 1; break + SCHK(INT); + SCHK(SHORT); + case BOOL: + SCHK(CHAR); + UCHK(UNSIGNED); + UCHK(USHORT); + UCHK(UCHAR); + default: + cerror("toolarge"); + } + return 0; +} +#endif + +#if defined(MACHOABI) + +/* + * Keep track of PIC stubs. + */ + +void +addstub(struct stub *list, char *name) +{ + struct stub *s; + + DLIST_FOREACH(s, list, link) { + if (strcmp(s->name, name) == 0) + return; + } + + s = permalloc(sizeof(struct stub)); + s->name = permalloc(strlen(name) + 1); + strcpy(s->name, name); + DLIST_INSERT_BEFORE(list, s, link); +} + +#endif + +#define IALLOC(sz) (isinlining ? permalloc(sz) : tmpalloc(sz)) + +/* + * Make a symtab entry for PIC use. + */ +static struct symtab * +picsymtab(char *p, char *s, char *s2) +{ + struct symtab *sp = IALLOC(sizeof(struct symtab)); + size_t len = strlen(p) + strlen(s) + strlen(s2) + 1; + + sp->sname = sp->soname = IALLOC(len); + strlcpy(sp->soname, p, len); + strlcat(sp->soname, s, len); + strlcat(sp->soname, s2, len); + sp->sap = NULL; + sp->sclass = EXTERN; + sp->sflags = sp->slevel = 0; + return sp; +} + +#ifdef os_win32 +static NODE * +import(NODE *p) +{ + NODE *q; + char *name; + struct symtab *sp; + + if ((name = p->n_sp->soname) == NULL) + name = exname(p->n_sp->sname); + + sp = picsymtab("__imp_", name, ""); + q = xbcon(0, sp, PTR+VOID); + q = block(UMUL, q, 0, PTR|VOID, 0, MKAP(VOID)); + q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap); + q->n_sp = p->n_sp; /* for init */ + nfree(p); + + return q; +} +#endif + +int gotnr; /* tempnum for GOT register */ +int argstacksize; + +/* + * Create a reference for an extern variable. + */ +static NODE * +picext(NODE *p) +{ + +#if defined(ELFABI) + + NODE *q, *r; + struct symtab *sp; + char *name; + + q = tempnode(gotnr, PTR|VOID, 0, MKAP(VOID)); + if ((name = p->n_sp->soname) == NULL) + name = p->n_sp->sname; + sp = picsymtab("", name, "@GOT"); +#ifdef GCC_COMPAT + if (attr_find(p->n_sp->sap, GCC_ATYP_STDCALL) != NULL) + p->n_sp->sflags |= SSTDCALL; +#endif + sp->sflags = p->n_sp->sflags & SSTDCALL; + r = xbcon(0, sp, INT); + q = buildtree(PLUS, q, r); + q = block(UMUL, q, 0, PTR|VOID, 0, MKAP(VOID)); + q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap); + q->n_sp = p->n_sp; /* for init */ + nfree(p); + return q; + +#elif defined(MACHOABI) + + NODE *q, *r; + struct symtab *sp; + char buf2[256], *name, *pspn; + + if ((name = cftnsp->soname) == NULL) + name = cftnsp->sname; + if ((pspn = p->n_sp->soname) == NULL) + pspn = exname(p->n_sp->sname); + if (p->n_sp->sclass == EXTDEF) { + snprintf(buf2, 256, "-L%s$pb", name); + sp = picsymtab("", pspn, buf2); + } else { + snprintf(buf2, 256, "$non_lazy_ptr-L%s$pb", name); + sp = picsymtab("L", pspn, buf2); + addstub(&nlplist, pspn); + } + q = tempnode(gotnr, PTR+VOID, 0, MKAP(VOID)); + r = xbcon(0, sp, INT); + q = buildtree(PLUS, q, r); + + if (p->n_sp->sclass != EXTDEF) + q = block(UMUL, q, 0, PTR+VOID, 0, MKAP(VOID)); + q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap); + q->n_sp = p->n_sp; /* for init */ + nfree(p); + return q; + +#elif defined(PECOFFABI) + + return p; + +#endif + +} + +/* + * Create a reference for a static variable. + */ +static NODE * +picstatic(NODE *p) +{ + +#if defined(ELFABI) + + NODE *q, *r; + struct symtab *sp; + + q = tempnode(gotnr, PTR|VOID, 0, MKAP(VOID)); + if (p->n_sp->slevel > 0) { + char buf[32]; + snprintf(buf, 32, LABFMT, (int)p->n_sp->soffset); + sp = picsymtab("", buf, "@GOTOFF"); + } else { + char *name; + if ((name = p->n_sp->soname) == NULL) + name = p->n_sp->sname; + sp = picsymtab("", name, "@GOTOFF"); + } + + sp->sclass = STATIC; + sp->stype = p->n_sp->stype; + r = xbcon(0, sp, INT); + q = buildtree(PLUS, q, r); + q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap); + q->n_sp = p->n_sp; /* for init */ + nfree(p); + return q; + +#elif defined(MACHOABI) + + NODE *q, *r; + struct symtab *sp; + char buf2[256]; + + snprintf(buf2, 256, "-L%s$pb", + cftnsp->soname ? cftnsp->soname : cftnsp->sname); + + if (p->n_sp->slevel > 0) { + char buf1[32]; + snprintf(buf1, 32, LABFMT, (int)p->n_sp->soffset); + sp = picsymtab("", buf1, buf2); + } else { + char *name; + if ((name = p->n_sp->soname) == NULL) + name = p->n_sp->sname; + sp = picsymtab("", exname(name), buf2); + } + sp->sclass = STATIC; + sp->stype = p->n_sp->stype; + q = tempnode(gotnr, PTR+VOID, 0, MKAP(VOID)); + r = xbcon(0, sp, INT); + q = buildtree(PLUS, q, r); + q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap); + q->n_sp = p->n_sp; + nfree(p); + return q; + +#elif defined(PECOFFABI) + + return p; + +#endif + +} + +#ifdef TLS +/* + * Create a reference for a TLS variable. + */ +static NODE * +tlspic(NODE *p) +{ + NODE *q, *r; + struct symtab *sp, *sp2; + char *name; + + /* + * creates: + * leal var@TLSGD(%ebx),%eax + * call ___tls_get_addr@PLT + */ + + /* calc address of var@TLSGD */ + q = tempnode(gotnr, PTR|VOID, 0, MKAP(VOID)); + if ((name = p->n_sp->soname) == NULL) + name = p->n_sp->sname; + sp = picsymtab("", name, "@TLSGD"); + r = xbcon(0, sp, INT); + q = buildtree(PLUS, q, r); + + /* assign to %eax */ + r = block(REG, NIL, NIL, PTR|VOID, 0, MKAP(VOID)); + r->n_rval = EAX; + q = buildtree(ASSIGN, r, q); + + /* call ___tls_get_addr */ + sp2 = lookup("___tls_get_addr@PLT", 0); + sp2->stype = EXTERN|INT|FTN; + r = nametree(sp2); + r = buildtree(ADDROF, r, NIL); + r = block(UCALL, r, NIL, INT, 0, MKAP(INT)); + + /* fusion both parts together */ + q = buildtree(COMOP, q, r); + q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap); + q->n_sp = p->n_sp; /* for init */ + + nfree(p); + return q; +} + +static NODE * +tlsnonpic(NODE *p) +{ + NODE *q, *r; + struct symtab *sp, *sp2; + int ext = p->n_sp->sclass; + char *name; + + if ((name = p->n_sp->soname) == NULL) + name = p->n_sp->sname; + sp = picsymtab("", name, + ext == EXTERN ? "@INDNTPOFF" : "@NTPOFF"); + q = xbcon(0, sp, INT); + if (ext == EXTERN) + q = block(UMUL, q, NIL, PTR|VOID, 0, MKAP(VOID)); + + sp2 = lookup("%gs:0", 0); + sp2->stype = EXTERN|INT; + r = nametree(sp2); + + q = buildtree(PLUS, q, r); + q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap); + q->n_sp = p->n_sp; /* for init */ + + nfree(p); + return q; +} + +static NODE * +tlsref(NODE *p) +{ + if (kflag) + return (tlspic(p)); + else + return (tlsnonpic(p)); +} +#endif + +/* clocal() is called to do local transformations on + * an expression tree preparitory to its being + * written out in intermediate code. + * + * the major essential job is rewriting the + * automatic variables and arguments in terms of + * REG and OREG nodes + * conversion ops which are not necessary are also clobbered here + * in addition, any special features (such as rewriting + * exclusive or) are easily handled here as well + */ +NODE * +clocal(NODE *p) +{ + + register struct symtab *q; + register NODE *r, *l; +#if defined(os_openbsd) + register NODE *s, *n; +#endif + register int o; + register int m; + +#ifdef PCC_DEBUG + if (xdebug) { + printf("clocal: %p\n", p); + fwalk(p, eprint, 0); + } +#endif + switch( o = p->n_op ){ + + case NAME: + if ((q = p->n_sp) == NULL) + return p; /* Nothing to care about */ + + switch (q->sclass) { + + case PARAM: + case AUTO: + /* fake up a structure reference */ + r = block(REG, NIL, NIL, PTR+STRTY, 0, 0); + r->n_lval = 0; + r->n_rval = FPREG; + p = stref(block(STREF, r, p, 0, 0, 0)); + break; + + case USTATIC: + if (kflag == 0) + break; + /* FALLTHROUGH */ + case STATIC: +#ifdef TLS + if (q->sflags & STLS) { + p = tlsref(p); + break; + } +#endif + if (kflag == 0) { + if (q->slevel == 0) + break; + p->n_lval = 0; + } else if (blevel > 0) + p = picstatic(p); + break; + + case REGISTER: + p->n_op = REG; + p->n_lval = 0; + p->n_rval = q->soffset; + break; + + case EXTERN: + case EXTDEF: +#ifdef TLS + if (q->sflags & STLS) { + p = tlsref(p); + break; + } +#endif + +#ifdef os_win32 + if (q->sflags & SDLLINDIRECT) + p = import(p); +#endif + if (kflag == 0) + break; + if (blevel > 0) + p = picext(p); + break; + } + break; + + case ADDROF: + if (kflag == 0 || blevel == 0) + break; + /* char arrays may end up here */ + l = p->n_left; + if (l->n_op != NAME || + (l->n_type != ARY+CHAR && l->n_type != ARY+WCHAR_TYPE)) + break; + l = p; + p = picstatic(p->n_left); + nfree(l); + if (p->n_op != UMUL) + cerror("ADDROF error"); + l = p; + p = p->n_left; + nfree(l); + break; + + case UCALL: + case USTCALL: + if (kflag == 0) + break; +#if defined(ELFABI) + /* Change to CALL node with ebx as argument */ + l = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + l->n_rval = EBX; + p->n_right = buildtree(ASSIGN, l, + tempnode(gotnr, INT, 0, MKAP(INT))); + p->n_op -= (UCALL-CALL); +#endif + + /* FALLTHROUGH */ +#if defined(MACHOABI) + case CALL: + case STCALL: + if (p->n_type == VOID) + break; + + r = tempnode(0, p->n_type, p->n_df, p->n_ap); + l = tcopy(r); + p = buildtree(COMOP, buildtree(ASSIGN, r, p), l); +#endif + + break; + +#ifdef notyet + /* XXX breaks sometimes */ + case CBRANCH: + l = p->n_left; + + /* + * Remove unnecessary conversion ops. + */ + if (!clogop(l->n_op) || l->n_left->n_op != SCONV) + break; + if (coptype(l->n_op) != BITYPE) + break; + if (l->n_right->n_op != ICON) + break; + r = l->n_left->n_left; + if (r->n_type >= FLOAT) + break; + if (toolarge(r->n_type, l->n_right->n_lval)) + break; + l->n_right->n_type = r->n_type; + if (l->n_op >= ULE && l->n_op <= UGT) + l->n_op -= (UGT-ULE); + p->n_left = buildtree(l->n_op, r, l->n_right); + nfree(l->n_left); + nfree(l); + break; +#endif + + case PCONV: + /* Remove redundant PCONV's. Be careful */ + l = p->n_left; + if (l->n_op == ICON) { + l->n_lval = (unsigned)l->n_lval; + goto delp; + } + if (l->n_type < INT || l->n_type == LONGLONG || + l->n_type == ULONGLONG) { + /* float etc? */ + p->n_left = block(SCONV, l, NIL, + UNSIGNED, 0, MKAP(UNSIGNED)); + break; + } + /* if left is SCONV, cannot remove */ + if (l->n_op == SCONV) + break; + + /* avoid ADDROF TEMP */ + if (l->n_op == ADDROF && l->n_left->n_op == TEMP) + break; + + /* if conversion to another pointer type, just remove */ + if (p->n_type > BTMASK && l->n_type > BTMASK) + goto delp; + break; + + delp: l->n_type = p->n_type; + l->n_qual = p->n_qual; + l->n_df = p->n_df; + l->n_ap = p->n_ap; + nfree(p); + p = l; + break; + + case SCONV: + if (p->n_left->n_op == COMOP) + break; /* may propagate wrong type later */ + l = p->n_left; + + if (p->n_type == l->n_type) { + nfree(p); + return l; + } + + if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 && + btattr[p->n_type].atypsz == btattr[l->n_type].atypsz) { + if (p->n_type != FLOAT && p->n_type != DOUBLE && + l->n_type != FLOAT && l->n_type != DOUBLE && + l->n_type != LDOUBLE && p->n_type != LDOUBLE) { + if (l->n_op == NAME || l->n_op == UMUL || + l->n_op == TEMP) { + l->n_type = p->n_type; + nfree(p); + return l; + } + } + } + + if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT && + coptype(l->n_op) == BITYPE && l->n_op != COMOP && + l->n_op != QUEST) { + l->n_type = p->n_type; + nfree(p); + return l; + } + + o = l->n_op; + m = p->n_type; + + if (o == ICON) { + CONSZ val = l->n_lval; + + if (!ISPTR(m)) /* Pointers don't need to be conv'd */ + switch (m) { + case BOOL: + l->n_lval = nncon(l) ? (l->n_lval != 0) : 1; + l->n_sp = NULL; + break; + case CHAR: + l->n_lval = (char)val; + break; + case UCHAR: + l->n_lval = val & 0377; + break; + case SHORT: + l->n_lval = (short)val; + break; + case USHORT: + l->n_lval = val & 0177777; + break; + case ULONG: + case UNSIGNED: + l->n_lval = val & 0xffffffff; + break; + case LONG: + case INT: + l->n_lval = (int)val; + break; + case LONGLONG: + l->n_lval = (long long)val; + break; + case ULONGLONG: + l->n_lval = val; + break; + case VOID: + break; + case LDOUBLE: + case DOUBLE: + case FLOAT: + l->n_op = FCON; + l->n_dcon = val; + break; + default: + cerror("unknown type %d", m); + } + l->n_type = m; + l->n_ap = MKAP(m); + nfree(p); + return l; + } else if (l->n_op == FCON) { + l->n_lval = (CONSZ)l->n_dcon; + l->n_sp = NULL; + l->n_op = ICON; + l->n_type = m; + l->n_ap = MKAP(m); + nfree(p); + return clocal(l); + } + if (DEUNSIGN(p->n_type) == SHORT && + DEUNSIGN(l->n_type) == SHORT) { + nfree(p); + p = l; + } + if ((p->n_type == CHAR || p->n_type == UCHAR || + p->n_type == SHORT || p->n_type == USHORT) && + (l->n_type == FLOAT || l->n_type == DOUBLE || + l->n_type == LDOUBLE)) { + p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_ap); + p->n_left->n_type = INT; + return p; + } + break; + + case MOD: + case DIV: + if (o == DIV && p->n_type != CHAR && p->n_type != SHORT) + break; + if (o == MOD && p->n_type != CHAR && p->n_type != SHORT) + break; + /* make it an int division by inserting conversions */ + p->n_left = block(SCONV, p->n_left, NIL, INT, 0, MKAP(INT)); + p->n_right = block(SCONV, p->n_right, NIL, INT, 0, MKAP(INT)); + p = block(SCONV, p, NIL, p->n_type, 0, MKAP(p->n_type)); + p->n_left->n_type = INT; + break; + + case PMCONV: + case PVCONV: + r = p; + p = buildtree(o == PMCONV ? MUL : DIV, p->n_left, p->n_right); + nfree(r); + break; + + case FORCE: + /* put return value in return reg */ + p->n_op = ASSIGN; + p->n_right = p->n_left; + p->n_left = block(REG, NIL, NIL, p->n_type, 0, MKAP(INT)); + p->n_left->n_rval = p->n_left->n_type == BOOL ? + RETREG(CHAR) : RETREG(p->n_type); + break; + + case LS: + case RS: + /* shift count must be in a char */ + if (p->n_right->n_type == CHAR || p->n_right->n_type == UCHAR) + break; + p->n_right = block(SCONV, p->n_right, NIL, CHAR, 0, MKAP(CHAR)); + break; +#if defined(os_openbsd) + /* If not using pcc struct return */ + case STASG: + r = p->n_right; + if (r->n_op != STCALL && r->n_op != USTCALL) + break; + m = tsize(BTYPE(r->n_type), r->n_df, r->n_ap); + if (m == SZCHAR) + m = CHAR; + else if (m == SZSHORT) + m = SHORT; + else if (m == SZINT) + m = INT; + else if (m == SZLONGLONG) + m = LONGLONG; + else + break; + + l = buildtree(ADDROF, p->n_left, NIL); + nfree(p); + + r->n_op -= (STCALL-CALL); + r->n_type = m; + + /* r = long, l = &struct */ + + n = tempnode(0, m, r->n_df, r->n_ap); + r = buildtree(ASSIGN, ccopy(n), r); + + s = tempnode(0, l->n_type, l->n_df, l->n_ap); + l = buildtree(ASSIGN, ccopy(s), l); + + p = buildtree(COMOP, r, l); + + l = buildtree(CAST, + block(NAME, NIL, NIL, m|PTR, 0, MKAP(m)), ccopy(s)); + r = l->n_right; + nfree(l->n_left); + nfree(l); + + r = buildtree(ASSIGN, buildtree(UMUL, r, NIL), n); + p = buildtree(COMOP, p, r); + p = buildtree(COMOP, p, s); + break; +#endif + } +#ifdef PCC_DEBUG + if (xdebug) { + printf("clocal end: %p\n", p); + fwalk(p, eprint, 0); + } +#endif + return(p); +} + +/* + * Change CALL references to either direct (static) or PLT. + */ +static void +fixnames(NODE *p, void *arg) +{ +#if !defined(PECOFFABI) + + struct symtab *sp; + struct attr *ap; + NODE *q; + char *c; + int isu; + + if ((cdope(p->n_op) & CALLFLG) == 0) + return; + isu = 0; + q = p->n_left; + ap = q->n_ap; + if (q->n_op == UMUL) + q = q->n_left, isu = 1; + + if (q->n_op == PLUS && q->n_left->n_op == TEMP && + q->n_right->n_op == ICON) { + sp = q->n_right->n_sp; + + if (sp == NULL) + return; /* nothing to do */ + if (sp->sclass == STATIC && !ISFTN(sp->stype)) + return; /* function pointer */ + + if (sp->sclass != STATIC && sp->sclass != EXTERN && + sp->sclass != EXTDEF) + cerror("fixnames"); + c = NULL; +#if defined(ELFABI) + + if (sp->soname == NULL || + (c = strstr(sp->soname, "@GOT")) == NULL) + cerror("fixnames2"); + if (isu) { + memcpy(c, "@PLT", sizeof("@PLT")); + } else + *c = 0; + +#elif defined(MACHOABI) + + if (sp->soname == NULL || + ((c = strstr(sp->soname, "$non_lazy_ptr")) == NULL && + (c = strstr(sp->soname, "-L")) == NULL)) + cerror("fixnames2"); + if (isu) { + *c = 0; + addstub(&stublist, sp->soname+1); + strcpy(c, "$stub"); + } else + *c = 0; + +#endif + + nfree(q->n_left); + q = q->n_right; + if (isu) + nfree(p->n_left->n_left); + nfree(p->n_left); + p->n_left = q; + q->n_ap = ap; + } +#endif +} + +static void mangle(NODE *p); + +void +myp2tree(NODE *p) +{ + struct symtab *sp; + + if (kflag) + fixnames(p, 0); + + mangle(p); + + if (p->n_op != FCON) + return; + + sp = IALLOC(sizeof(struct symtab)); + sp->sclass = STATIC; + sp->sap = MKAP(p->n_type); + sp->slevel = 1; /* fake numeric label */ + sp->soffset = getlab(); + sp->sflags = 0; + sp->stype = p->n_type; + sp->squal = (CON >> TSHIFT); + + defloc(sp); + ninval(0, sp->sap->atypsz, p); + + p->n_op = NAME; + p->n_lval = 0; + p->n_sp = sp; +} + +/*ARGSUSED*/ +int +andable(NODE *p) +{ + return(1); /* all names can have & taken on them */ +} + +/* + * at the end of the arguments of a ftn, set the automatic offset + */ +void +cendarg() +{ + autooff = AUTOINIT; +} + +/* + * Return 1 if a variable of type type is OK to put in register. + */ +int +cisreg(TWORD t) +{ + if (t == FLOAT || t == DOUBLE || t == LDOUBLE) + return 0; /* not yet */ + return 1; +} + +/* + * return a node, for structure references, which is suitable for + * being added to a pointer of type t, in order to be off bits offset + * into a structure + * t, d, and s are the type, dimension offset, and sizeoffset + * For pdp10, return the type-specific index number which calculation + * is based on its size. For example, short a[3] would return 3. + * Be careful about only handling first-level pointers, the following + * indirections must be fullword. + */ +NODE * +offcon(OFFSZ off, TWORD t, union dimfun *d, struct attr *ap) +{ + register NODE *p; + + if (xdebug) + printf("offcon: OFFSZ %lld type %x dim %p siz %d\n", + off, t, d, 0); + + p = bcon(0); + p->n_lval = off/SZCHAR; /* Default */ + return(p); +} + +/* + * Allocate off bits on the stack. p is a tree that when evaluated + * is the multiply count for off, t is a storeable node where to write + * the allocated address. + */ +void +spalloc(NODE *t, NODE *p, OFFSZ off) +{ + NODE *sp; + + p = buildtree(MUL, p, bcon(off/SZCHAR)); /* XXX word alignment? */ + + /* sub the size from sp */ + sp = block(REG, NIL, NIL, p->n_type, 0, MKAP(INT)); + sp->n_lval = 0; + sp->n_rval = STKREG; + ecomp(buildtree(MINUSEQ, sp, p)); + +#ifdef MACHOABI + /* align to 16 bytes */ + sp = block(REG, NIL, NIL, p->n_type, 0, MKAP(INT)); + sp->n_lval = 0; + sp->n_rval = STKREG; + ecomp(buildtree(PLUSEQ, sp, bcon(15))); + + sp = block(REG, NIL, NIL, p->n_type, 0, MKAP(INT)); + sp->n_lval = 0; + sp->n_rval = STKREG; + ecomp(buildtree(RSEQ, sp, bcon(4))); + + sp = block(REG, NIL, NIL, p->n_type, 0, MKAP(INT)); + sp->n_lval = 0; + sp->n_rval = STKREG; + ecomp(buildtree(LSEQ, sp, bcon(4))); +#endif + + + /* save the address of sp */ + sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_ap); + sp->n_lval = 0; + sp->n_rval = STKREG; + t->n_type = sp->n_type; + ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */ + +} + +/* + * Print out a string of characters. + * Assume that the assembler understands C-style escape + * sequences. + */ +void +instring(struct symtab *sp) +{ + char *s, *str = sp->sname; + +#if defined(ELFABI) || defined(PECOFFABI) + + defloc(sp); + +#elif defined(MACHOABI) + + extern int lastloc; + if (lastloc != STRNG) + printf(" .cstring\n"); + lastloc = STRNG; + printf("\t.p2align 2\n"); + printf(LABFMT ":\n", sp->soffset); + +#endif + + /* be kind to assemblers and avoid long strings */ + printf("\t.ascii \""); + for (s = str; *s != 0; ) { + if (*s++ == '\\') { + (void)esccon(&s); + } + if (s - str > 60) { + fwrite(str, 1, s - str, stdout); + printf("\"\n\t.ascii \""); + str = s; + } + } + fwrite(str, 1, s - str, stdout); + printf("\\0\"\n"); +} + +static int inbits, inval; + +/* + * set fsz bits in sequence to zero. + */ +void +zbits(OFFSZ off, int fsz) +{ + int m; + + if (idebug) + printf("zbits off %lld, fsz %d inbits %d\n", off, fsz, inbits); + if ((m = (inbits % SZCHAR))) { + m = SZCHAR - m; + if (fsz < m) { + inbits += fsz; + return; + } else { + fsz -= m; + printf("\t.byte %d\n", inval); + inval = inbits = 0; + } + } + if (fsz >= SZCHAR) { +#ifdef os_darwin + printf("\t.space %d\n", fsz/SZCHAR); +#else + printf("\t.zero %d\n", fsz/SZCHAR); +#endif + fsz -= (fsz/SZCHAR) * SZCHAR; + } + if (fsz) { + inval = 0; + inbits = fsz; + } +} + +/* + * Initialize a bitfield. + */ +void +infld(CONSZ off, int fsz, CONSZ val) +{ + if (idebug) + printf("infld off %lld, fsz %d, val %lld inbits %d\n", + off, fsz, val, inbits); + val &= ((CONSZ)1 << fsz)-1; + while (fsz + inbits >= SZCHAR) { + inval |= (int)(val << inbits); + printf("\t.byte %d\n", inval & 255); + fsz -= (SZCHAR - inbits); + val >>= (SZCHAR - inbits); + inval = inbits = 0; + } + if (fsz) { + inval |= (int)(val << inbits); + inbits += fsz; + } +} + +/* + * print out a constant node, may be associated with a label. + * Do not free the node after use. + * off is bit offset from the beginning of the aggregate + * fsz is the number of bits this is referring to + */ +void +ninval(CONSZ off, int fsz, NODE *p) +{ + union { float f; double d; long double l; int i[3]; } u; + struct symtab *q; +#if defined(ELFABI) || defined(MACHOABI) + char *c; +#endif + TWORD t; + int i; + + t = p->n_type; + if (t > BTMASK) + t = INT; /* pointer */ + + while (p->n_op == SCONV || p->n_op == PCONV) { + NODE *l = p->n_left; + l->n_type = p->n_type; + p = l; + } + + if (kflag && (p->n_op == PLUS || p->n_op == UMUL)) { + if (p->n_op == UMUL) + p = p->n_left; + p = p->n_right; + q = p->n_sp; + + if (q->soname != NULL) { +#if defined(ELFABI) + + if ((c = strstr(q->soname, "@GOT")) != NULL) + *c = 0; /* ignore GOT ref here */ +#elif defined(MACHOABI) + + if ((c = strstr(q->soname, "$non_lazy_ptr")) != NULL) { + q->soname++; /* skip "L" */ + *c = 0; /* ignore GOT ref here */ + } else if ((c = strstr(q->soname, "-L")) != NULL) + *c = 0; /* ignore GOT ref here */ +#endif + } + } + if (p->n_op != ICON && p->n_op != FCON) + cerror("ninval: init node not constant"); + + if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT) + uerror("element not constant"); + + switch (t) { + case LONGLONG: + case ULONGLONG: + i = (int)(p->n_lval >> 32); + p->n_lval &= 0xffffffff; + p->n_type = INT; + ninval(off, 32, p); + p->n_lval = i; + ninval(off+32, 32, p); + break; + case INT: + case UNSIGNED: + printf("\t.long %d", (int)p->n_lval); + if ((q = p->n_sp) != NULL) { + if ((q->sclass == STATIC && q->slevel > 0)) { + printf("+" LABFMT, q->soffset); + } else { + char *name; + if ((name = q->soname) == NULL) + name = exname(q->sname); + printf("+%s", name); + } + } + printf("\n"); + break; + case SHORT: + case USHORT: +#ifdef os_sunos + printf("\t.2byte 0x%x\n", (int)p->n_lval & 0xffff); +#else + printf("\t.short 0x%x\n", (int)p->n_lval & 0xffff); +#endif + break; + case BOOL: + if (p->n_lval > 1) + p->n_lval = p->n_lval != 0; + /* FALLTHROUGH */ + case CHAR: + case UCHAR: + printf("\t.byte %d\n", (int)p->n_lval & 0xff); + break; + case LDOUBLE: + u.i[2] = 0; + u.l = (long double)p->n_dcon; +#if defined(HOST_BIG_ENDIAN) + /* XXX probably broken on most hosts */ + printf("\t.long\t0x%x,0x%x,0x%x\n", u.i[2], u.i[1], u.i[0]); +#else + printf("\t.long\t%d,%d,%d\n", u.i[0], u.i[1], u.i[2] & 0177777); +#endif + break; + case DOUBLE: + u.d = (double)p->n_dcon; +#if defined(HOST_BIG_ENDIAN) + printf("\t.long\t0x%x,0x%x\n", u.i[1], u.i[0]); +#else + printf("\t.long\t%d,%d\n", u.i[0], u.i[1]); +#endif + break; + case FLOAT: + u.f = (float)p->n_dcon; + printf("\t.long\t%d\n", u.i[0]); + break; + default: + cerror("ninval"); + } +} + +/* make a name look like an external name in the local machine */ +char * +exname(char *p) +{ +#if defined(PECOFFABI) || defined(MACHOABI) + +#define NCHNAM 256 + static char text[NCHNAM+1]; + int i; + + if (p == NULL) + return ""; + + text[0] = '_'; + for (i=1; *p && isflags & STLS) { + if (sp->sclass == EXTERN) + sp->sclass = EXTDEF; + simpleinit(sp, bcon(0)); + return; + } +#endif + + if ((name = sp->soname) == NULL) + name = exname(sp->sname); + al = talign(sp->stype, sp->sap)/SZCHAR; + off = (int)tsize(sp->stype, sp->sdf, sp->sap); + off = (off+(SZCHAR-1))/SZCHAR; +#ifdef GCC_COMPAT + { + struct attr *ap; + if ((ap = attr_find(sp->sap, GCC_ATYP_VISIBILITY)) && + strcmp(ap->sarg(0), "default")) + printf("\t.%s %s\n", ap->sarg(0), name); + } +#endif + printf(" .%scomm ", sp->sclass == STATIC ? "l" : ""); + if (sp->slevel == 0) + printf("%s,0%o", name, off); + else + printf(LABFMT ",0%o", sp->soffset, off); + if (sp->sclass != STATIC) { +#if defined(ELFABI) + printf(",%d", al); +#elif defined(MACHOABI) + printf(",%d", ispow2(al)); +#endif + } + printf("\n"); +} + +static char * +section2string(char *name, int len) +{ +#if defined(ELFABI) + char *s; + int n; + + if (strncmp(name, "link_set", 8) == 0) { + const char *postfix = ",\"aw\",@progbits"; + n = len + strlen(postfix) + 1; + s = IALLOC(n); + strlcpy(s, name, n); + strlcat(s, postfix, n); + return s; + } +#endif + + return newstring(name, len); +} + +char *nextsect; +#ifdef TLS +static int gottls; +#endif +static int stdcall; +#ifdef os_win32 +static int dllindirect; +#endif +static char *alias; +static int constructor; +static int destructor; + +/* + * Give target the opportunity of handling pragmas. + */ +int +mypragma(char *str) +{ + char *a2 = pragtok(NULL); + +#ifdef TLS + if (strcmp(str, "tls") == 0 && a2 == NULL) { + gottls = 1; + return 1; + } +#endif + if (strcmp(str, "stdcall") == 0) { + stdcall = 1; + return 1; + } + if (strcmp(str, "cdecl") == 0) { + stdcall = 0; + return 1; + } +#ifdef os_win32 + if (strcmp(str, "fastcall") == 0) { + stdcall = 2; + return 1; + } + if (strcmp(str, "dllimport") == 0) { + dllindirect = 1; + return 1; + } + if (strcmp(str, "dllexport") == 0) { + dllindirect = 1; + return 1; + } +#endif + if (strcmp(str, "constructor") == 0 || strcmp(str, "init") == 0) { + constructor = 1; + return 1; + } + if (strcmp(str, "destructor") == 0 || strcmp(str, "fini") == 0) { + destructor = 1; + return 1; + } + if (strcmp(str, "section") == 0 && a2 != NULL) { + nextsect = section2string(a2, strlen(a2)); + return 1; + } + if (strcmp(str, "alias") == 0 && a2 != NULL) { + alias = tmpstrdup(a2); + return 1; + } + if (strcmp(str, "ident") == 0) + return 1; /* Just ignore */ + + return 0; +} + +/* + * Called when a identifier has been declared. + */ +void +fixdef(struct symtab *sp) +{ + struct attr *ap; +#ifdef TLS + /* may have sanity checks here */ + if (gottls) + sp->sflags |= STLS; + gottls = 0; +#endif + if ((ap = attr_find(sp->sap, GCC_ATYP_ALIAS)) != NULL) { + char *an = ap->sarg(0); + char *sn = sp->soname ? sp->soname : sp->sname; + char *v; + + v = attr_find(sp->sap, GCC_ATYP_WEAK) ? "weak" : "globl"; + printf("\t.%s %s\n", v, sn); + printf("\t.set %s,%s\n", sn, an); + } + + if (alias != NULL && (sp->sclass != PARAM)) { + char *name; + if ((name = sp->soname) == NULL) + name = exname(sp->sname); + printf("\t.globl %s\n", name); + printf("%s = ", name); + printf("%s\n", exname(alias)); + alias = NULL; + } + if ((constructor || destructor) && (sp->sclass != PARAM)) { +#if defined(ELFABI) + printf("\t.section .%ctors,\"aw\",@progbits\n", + constructor ? 'c' : 'd'); +#elif defined(PECOFFABI) + printf("\t.section .%ctors,\"w\"\n", + constructor ? 'c' : 'd'); +#elif defined(MACHOABI) + if (kflag) { + if (constructor) + printf("\t.mod_init_func\n"); + else + printf("\t.mod_term_func\n"); + } else { + if (constructor) + printf("\t.constructor\n"); + else + printf("\t.destructor\n"); + } +#endif + printf("\t.p2align 2\n"); + printf("\t.long %s\n", exname(sp->sname)); +#ifdef MACHOABI + printf("\t.text\n"); +#else + printf("\t.previous\n"); +#endif + constructor = destructor = 0; + } + if (stdcall && (sp->sclass != PARAM)) { + sp->sflags |= SSTDCALL; + stdcall = 0; + } +#ifdef os_win32 + if (dllindirect && (sp->sclass != PARAM)) { + sp->sflags |= SDLLINDIRECT; + dllindirect = 0; + } +#endif +} + +NODE * +i386_builtin_return_address(NODE *f, NODE *a, TWORD rt) +{ + int nframes; + + if (a == NULL || a->n_op != ICON) + goto bad; + + nframes = (int)a->n_lval; + + tfree(f); + tfree(a); + + f = block(REG, NIL, NIL, PTR+VOID, 0, MKAP(VOID)); + regno(f) = FPREG; + + while (nframes--) + f = block(UMUL, f, NIL, PTR+VOID, 0, MKAP(VOID)); + + f = block(PLUS, f, bcon(4), INCREF(PTR+VOID), 0, MKAP(VOID)); + f = buildtree(UMUL, f, NIL); + + return f; +bad: + uerror("bad argument to __builtin_return_address"); + return bcon(0); +} + +NODE * +i386_builtin_frame_address(NODE *f, NODE *a, TWORD rt) +{ + int nframes; + + if (a == NULL || a->n_op != ICON) + goto bad; + + nframes = (int)a->n_lval; + + tfree(f); + tfree(a); + + f = block(REG, NIL, NIL, PTR+VOID, 0, MKAP(VOID)); + regno(f) = FPREG; + + while (nframes--) + f = block(UMUL, f, NIL, PTR+VOID, 0, MKAP(VOID)); + + return f; +bad: + uerror("bad argument to __builtin_frame_address"); + return bcon(0); +} + +/* + * Postfix external functions with the arguments size. + */ +static void +mangle(NODE *p) +{ + NODE *l; + + if (p->n_op == NAME || p->n_op == ICON) { + p->n_flags = 0; /* for later setting of STDCALL */ + if (p->n_sp) { + if (p->n_sp->sflags & SSTDCALL) + p->n_flags = FSTDCALL; + } + } else if (p->n_op == TEMP) + p->n_flags = 0; /* STDCALL fun ptr not allowed */ + + if (p->n_op != CALL && p->n_op != STCALL && + p->n_op != UCALL && p->n_op != USTCALL) + return; + + p->n_flags = 0; + + l = p->n_left; + while (cdope(l->n_op) & CALLFLG) + l = l->n_left; + if (l->n_op == TEMP) + return; + if (l->n_op == ADDROF) + l = l->n_left; + if (l->n_sp == NULL) + return; +#ifdef GCC_COMPAT + if (attr_find(l->n_sp->sap, GCC_ATYP_STDCALL) != NULL) + l->n_sp->sflags |= SSTDCALL; +#endif +#ifdef os_win32 + if (l->n_sp->sflags & SSTDCALL) { + if (strchr(l->n_name, '@') == NULL) { + int size = 0; + char buf[256]; + NODE *r; + TWORD t; + + if (p->n_op == CALL || p->n_op == STCALL) { + for (r = p->n_right; + r->n_op == CM; r = r->n_left) { + t = r->n_type; + if (t == STRTY || t == UNIONTY) + size += tsize(t, r->n_df, r->n_ap); + else + size += szty(t) * SZINT / SZCHAR; + } + t = r->n_type; + if (t == STRTY || t == UNIONTY) + size += tsize(t, r->n_df, r->n_ap); + else + size += szty(t) * SZINT / SZCHAR; + } + snprintf(buf, 256, "%s@%d", l->n_name, size); + l->n_name = IALLOC(strlen(buf) + 1); + strcpy(l->n_name, buf); + } + } +#endif +} + +void +pass1_lastchance(struct interpass *ip) +{ + if (ip->type == IP_NODE && + (ip->ip_node->n_op == CALL || ip->ip_node->n_op == UCALL) && + ISFTY(ip->ip_node->n_type)) + ip->ip_node->n_flags = FFPPOP; + + if (ip->type == IP_EPILOG) { + struct interpass_prolog *ipp = (struct interpass_prolog *)ip; + ipp->ipp_argstacksize = argstacksize; + } +} diff --git a/compilers/pcc/pcc-1.0.0/arch/i386/local2.c b/compilers/pcc/pcc-1.0.0/arch/i386/local2.c new file mode 100644 index 00000000..aab7b9af --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/i386/local2.c @@ -0,0 +1,1602 @@ +/* $Id: local2.c,v 1.154.2.2 2011/02/26 07:17:34 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +# include "pass2.h" +# include +# include + +#if defined(PECOFFABI) || defined(MACHOABI) +#define EXPREFIX "_" +#else +#define EXPREFIX "" +#endif + + +static int stkpos; + +void +deflab(int label) +{ + printf(LABFMT ":\n", label); +} + +static int regoff[7]; +static TWORD ftype; + +/* + * Print out the prolog assembler. + * addto and regoff are already calculated. + */ +static void +prtprolog(struct interpass_prolog *ipp, int addto) +{ + int i; + + printf(" pushl %%ebp\n"); + printf(" movl %%esp,%%ebp\n"); +#if defined(MACHOABI) + printf(" subl $8,%%esp\n"); /* 16-byte stack alignment */ +#endif + if (addto) + printf(" subl $%d,%%esp\n", addto); + for (i = 0; i < MAXREGS; i++) + if (TESTBIT(ipp->ipp_regs, i)) + fprintf(stdout, " movl %s,-%d(%s)\n", + rnames[i], regoff[i], rnames[FPREG]); +} + +/* + * calculate stack size and offsets + */ +static int +offcalc(struct interpass_prolog *ipp) +{ + int i, addto; + + addto = p2maxautooff; + if (addto >= AUTOINIT/SZCHAR) + addto -= AUTOINIT/SZCHAR; + for (i = 0; i < MAXREGS; i++) + if (TESTBIT(ipp->ipp_regs, i)) { + addto += SZINT/SZCHAR; + regoff[i] = addto; + } + return addto; +} + +void +prologue(struct interpass_prolog *ipp) +{ + int addto; + + ftype = ipp->ipp_type; + +#ifdef LANG_F77 + if (ipp->ipp_vis) + printf(" .globl %s\n", ipp->ipp_name); + printf(" .align 4\n"); + printf("%s:\n", ipp->ipp_name); +#endif + /* + * We here know what register to save and how much to + * add to the stack. + */ + addto = offcalc(ipp); +#if defined(MACHOABI) + addto = (addto + 15) & ~15; /* stack alignment */ +#endif + prtprolog(ipp, addto); +} + +void +eoftn(struct interpass_prolog *ipp) +{ + int i; + + if (ipp->ipp_ip.ip_lbl == 0) + return; /* no code needs to be generated */ + + /* return from function code */ + for (i = 0; i < MAXREGS; i++) + if (TESTBIT(ipp->ipp_regs, i)) + fprintf(stdout, " movl -%d(%s),%s\n", + regoff[i], rnames[FPREG], rnames[i]); + + /* struct return needs special treatment */ + if (ftype == STRTY || ftype == UNIONTY) { + printf(" movl 8(%%ebp),%%eax\n"); + printf(" leave\n"); + printf(" ret $%d\n", 4 + ipp->ipp_argstacksize); + } else { + printf(" leave\n"); + if (ipp->ipp_argstacksize) + printf(" ret $%d\n", ipp->ipp_argstacksize); + else + printf(" ret\n"); + } + +#if defined(ELFABI) + printf("\t.size " EXPREFIX "%s,.-" EXPREFIX "%s\n", ipp->ipp_name, + ipp->ipp_name); +#endif +} + +/* + * add/sub/... + * + * Param given: + */ +void +hopcode(int f, int o) +{ + char *str; + + switch (o) { + case PLUS: + str = "add"; + break; + case MINUS: + str = "sub"; + break; + case AND: + str = "and"; + break; + case OR: + str = "or"; + break; + case ER: + str = "xor"; + break; + default: + comperr("hopcode2: %d", o); + str = 0; /* XXX gcc */ + } + printf("%s%c", str, f); +} + +/* + * Return type size in bytes. Used by R2REGS, arg 2 to offset(). + */ +int +tlen(p) NODE *p; +{ + switch(p->n_type) { + case CHAR: + case UCHAR: + return(1); + + case SHORT: + case USHORT: + return(SZSHORT/SZCHAR); + + case DOUBLE: + return(SZDOUBLE/SZCHAR); + + case INT: + case UNSIGNED: + case LONG: + case ULONG: + return(SZINT/SZCHAR); + + case LONGLONG: + case ULONGLONG: + return SZLONGLONG/SZCHAR; + + default: + if (!ISPTR(p->n_type)) + comperr("tlen type %d not pointer"); + return SZPOINT(p->n_type)/SZCHAR; + } +} + +/* + * Emit code to compare two longlong numbers. + */ +static void +twollcomp(NODE *p) +{ + int u; + int s = getlab2(); + int e = p->n_label; + int cb1, cb2; + + u = p->n_op; + switch (p->n_op) { + case NE: + cb1 = 0; + cb2 = NE; + break; + case EQ: + cb1 = NE; + cb2 = 0; + break; + case LE: + case LT: + u += (ULE-LE); + /* FALLTHROUGH */ + case ULE: + case ULT: + cb1 = GT; + cb2 = LT; + break; + case GE: + case GT: + u += (ULE-LE); + /* FALLTHROUGH */ + case UGE: + case UGT: + cb1 = LT; + cb2 = GT; + break; + + default: + cb1 = cb2 = 0; /* XXX gcc */ + } + if (p->n_op >= ULE) + cb1 += 4, cb2 += 4; + expand(p, 0, " cmpl UR,UL\n"); + if (cb1) cbgen(cb1, s); + if (cb2) cbgen(cb2, e); + expand(p, 0, " cmpl AR,AL\n"); + cbgen(u, e); + deflab(s); +} + +int +fldexpand(NODE *p, int cookie, char **cp) +{ + CONSZ val; + + if (p->n_op == ASSIGN) + p = p->n_left; + switch (**cp) { + case 'S': + printf("%d", UPKFSZ(p->n_rval)); + break; + case 'H': + printf("%d", UPKFOFF(p->n_rval)); + break; + case 'M': + case 'N': + val = (CONSZ)1 << UPKFSZ(p->n_rval); + --val; + val <<= UPKFOFF(p->n_rval); + printf("0x%llx", (**cp == 'M' ? val : ~val) & 0xffffffff); + break; + default: + comperr("fldexpand"); + } + return 1; +} + +static void +bfext(NODE *p) +{ + int ch = 0, sz = 0; + + if (ISUNSIGNED(p->n_right->n_type)) + return; + switch (p->n_right->n_type) { + case CHAR: + ch = 'b'; + sz = 8; + break; + case SHORT: + ch = 'w'; + sz = 16; + break; + case INT: + case LONG: + ch = 'l'; + sz = 32; + break; + default: + comperr("bfext"); + } + + sz -= UPKFSZ(p->n_left->n_rval); + printf("\tshl%c $%d,", ch, sz); + adrput(stdout, getlr(p, 'D')); + printf("\n\tsar%c $%d,", ch, sz); + adrput(stdout, getlr(p, 'D')); + printf("\n"); +} + +/* long long bitfield assign */ +static void +llbf(NODE *p) +{ + NODE *q; + char buf[50]; + CONSZ m, n; + int o, s; + int ml, mh, nl, nh; + + q = p->n_left; + o = UPKFOFF(q->n_rval); + s = UPKFSZ(q->n_rval); + m = (CONSZ)1 << (s-1); + m--; + m = (m << 1) | 1; + m <<= o; + n = ~m; + + ml = m & 0xffffffff; + nl = n & 0xffffffff; + mh = (m >> 32) & 0xffffffff; + nh = (n >> 32) & 0xffffffff; + +#define S(...) snprintf(buf, sizeof buf, __VA_ARGS__); expand(p, 0, buf) + + if (o < 32) { /* lower 32 buts */ + S(" andl $0x%x,AL\n", nl); + S(" movl AR,A1\n"); + S(" sall $%d,A1\n", o); + S(" andl $0x%x,A1\n", ml); + S(" orl A1,AL\n"); + } + if ((o+s) >= 32) { /* upper 32 bits */ + S(" andl $0x%x,UL\n", nh); + S(" movl UR,A1\n"); + S(" sall $%d,A1\n", o); + S(" movl AR,U1\n"); + S(" shrl $%d,U1\n", 32-o); + S(" orl U1,A1\n"); + S(" andl $0x%x,A1\n", mh); + S(" orl A1,UL\n"); + } +#undef S +// fwalk(p, e2print, 0); + + +} + +/* + * Push a structure on stack as argument. + * the scratch registers are already free here + */ +static void +starg(NODE *p) +{ + FILE *fp = stdout; + +#if defined(MACHOABI) + fprintf(fp, " subl $%d,%%esp\n", p->n_stsize); + fprintf(fp, " subl $4,%%esp\n"); + fprintf(fp, " pushl $%d\n", p->n_stsize); + expand(p, 0, " pushl AL\n"); + expand(p, 0, " leal 12(%esp),A1\n"); + expand(p, 0, " pushl A1\n"); + if (kflag) { + fprintf(fp, " call L%s$stub\n", EXPREFIX "memcpy"); + addstub(&stublist, EXPREFIX "memcpy"); + } else { + fprintf(fp, " call %s\n", EXPREFIX "memcpy"); + } + fprintf(fp, " addl $16,%%esp\n"); +#else + fprintf(fp, " subl $%d,%%esp\n", (p->n_stsize+3) & ~3); + fprintf(fp, " pushl $%d\n", p->n_stsize); + expand(p, 0, " pushl AL\n"); + expand(p, 0, " leal 8(%esp),A1\n"); + expand(p, 0, " pushl A1\n"); + fprintf(fp, " call %s%s\n", EXPREFIX "memcpy", kflag ? "@PLT" : ""); + fprintf(fp, " addl $12,%%esp\n"); +#endif +} + +/* + * Compare two floating point numbers. + */ +static void +fcomp(NODE *p) +{ + static char *fpcb[] = { "jz", "jnz", "jbe", "jc", "jnc", "ja" }; + + if ((p->n_su & DORIGHT) == 0) + expand(p, 0, " fxch\n"); + expand(p, 0, " fucomip %st(1),%st\n"); /* emit compare insn */ + expand(p, 0, " fstp %st(0)\n"); /* pop fromstack */ + + if (p->n_op == NE || p->n_op == GT || p->n_op == GE) + expand(p, 0, " jp LC\n"); + else if (p->n_op == EQ) + printf("\tjp 1f\n"); + printf(" %s ", fpcb[p->n_op - EQ]); + expand(p, 0, "LC\n"); + if (p->n_op == EQ) + printf("1:\n"); +} + +/* + * Convert an unsigned long long to floating point number. + */ +static void +ulltofp(NODE *p) +{ + static int loadlab; + int jmplab; + + if (loadlab == 0) { + loadlab = getlab2(); + expand(p, 0, " .data\n"); + printf(LABFMT ": .long 0,0x80000000,0x403f\n", loadlab); + expand(p, 0, " .text\n"); + } + jmplab = getlab2(); + expand(p, 0, " pushl UL\n pushl AL\n"); + expand(p, 0, " fildq (%esp)\n"); + expand(p, 0, " addl $8,%esp\n"); + expand(p, 0, " cmpl $0,UL\n"); + printf(" jge " LABFMT "\n", jmplab); + printf(" fldt " LABFMT "\n", loadlab); + printf(" faddp %%st,%%st(1)\n"); + printf(LABFMT ":\n", jmplab); +} + +static int +argsiz(NODE *p) +{ + TWORD t = p->n_type; + + if (t < LONGLONG || t == FLOAT || t > BTMASK) + return 4; + if (t == LONGLONG || t == ULONGLONG || t == DOUBLE) + return 8; + if (t == LDOUBLE) + return 12; + if (t == STRTY || t == UNIONTY) + return (p->n_stsize+3) & ~3; + comperr("argsiz"); + return 0; +} + +static void +fcast(NODE *p) +{ + TWORD t = p->n_type; + int sz, c; + + if (t >= p->n_left->n_type) + return; /* cast to more precision */ + if (t == FLOAT) + sz = 4, c = 's'; + else + sz = 8, c = 'l'; + + printf(" sub $%d,%%esp\n", sz); + printf(" fstp%c (%%esp)\n", c); + printf(" fld%c (%%esp)\n", c); + printf(" add $%d,%%esp\n", sz); +} + +static void +llshft(NODE *p) +{ + char *d[3]; + + if (p->n_op == LS) { + d[0] = "l", d[1] = "%eax", d[2] = "%edx"; + } else + d[0] = "r", d[1] = "%edx", d[2] = "%eax"; + + printf("\tsh%sdl %s,%s\n",d[0], d[1], d[2]); + printf("\ts%s%sl %%cl,%s\n", p->n_op == RS && + p->n_left->n_type == ULONGLONG ? "h" : "a", d[0], d[1]); + printf("\ttestb $32,%%cl\n"); + printf("\tje 1f\n"); + printf("\tmovl %s,%s\n", d[1], d[2]); + if (p->n_op == RS && p->n_left->n_type == LONGLONG) + printf("\tsarl $31,%%edx\n"); + else + printf("\txorl %s,%s\n",d[1],d[1]); + printf("1:\n"); +} + +void +zzzcode(NODE *p, int c) +{ + NODE *l; + int pr, lr, s; + char *ch; + + switch (c) { + case 'A': /* swap st0 and st1 if right is evaluated second */ + if ((p->n_su & DORIGHT) == 0) { + if (logop(p->n_op)) + printf(" fxch\n"); + else + printf("r"); + } + break; + + case 'B': { /* packed bitfield ops */ + int sz, off; + + l = p->n_left; + sz = UPKFSZ(l->n_rval); + off = UPKFOFF(l->n_rval); + if (sz + off <= SZINT) + break; + /* lower already printed */ + expand(p, INAREG, " movl AR,A1\n"); + expand(p, INAREG, " andl $M,UL\n"); + printf(" sarl $%d,", SZINT-off); + expand(p, INAREG, "A1\n"); + expand(p, INAREG, " andl $N,A1\n"); + expand(p, INAREG, " orl A1,UL\n"); + } + break; + + case 'C': /* remove from stack after subroutine call */ +#ifdef notyet + if (p->n_left->n_flags & FSTDCALL) + break; +#endif + pr = p->n_qual; + if (p->n_op == STCALL || p->n_op == USTCALL) + pr += 4; + if (p->n_flags & FFPPOP) + printf(" fstp %%st(0)\n"); + if (p->n_op == UCALL) + return; /* XXX remove ZC from UCALL */ + if (pr) + printf(" addl $%d, %s\n", pr, rnames[ESP]); + break; + + case 'D': /* Long long comparision */ + twollcomp(p); + break; + + case 'E': /* Perform bitfield sign-extension */ + bfext(p); + break; + + case 'F': /* Structure argument */ + if (p->n_stalign != 0) /* already on stack */ + starg(p); + break; + + case 'G': /* Floating point compare */ + fcomp(p); + break; + + case 'H': /* assign of longlong between regs */ + rmove(DECRA(p->n_right->n_reg, 0), + DECRA(p->n_left->n_reg, 0), LONGLONG); + break; + + case 'I': /* float casts */ + fcast(p); + break; + + case 'J': /* convert unsigned long long to floating point */ + ulltofp(p); + break; + + case 'K': /* Load longlong reg into another reg */ + rmove(regno(p), DECRA(p->n_reg, 0), LONGLONG); + break; + + case 'L': /* long long bitfield assign */ + llbf(p); + break; + + case 'M': /* Output sconv move, if needed */ + l = getlr(p, 'L'); + /* XXX fixneed: regnum */ + pr = DECRA(p->n_reg, 0); + lr = DECRA(l->n_reg, 0); + if ((pr == AL && lr == EAX) || (pr == BL && lr == EBX) || + (pr == CL && lr == ECX) || (pr == DL && lr == EDX)) + ; + else + printf(" movb %%%cl,%s\n", + rnames[lr][2], rnames[pr]); + l->n_rval = l->n_reg = p->n_reg; /* XXX - not pretty */ + break; + + case 'N': /* output extended reg name */ + printf("%s", rnames[getlr(p, '1')->n_rval]); + break; + + case 'O': /* print out emulated ops */ + pr = 16; + if (p->n_op == RS || p->n_op == LS) { + llshft(p); + break; + } else if (p->n_op == MUL) { + printf("\timull %%ecx, %%edx\n"); + printf("\timull %%eax, %%esi\n"); + printf("\taddl %%edx, %%esi\n"); + printf("\tmull %%ecx\n"); + printf("\taddl %%esi, %%edx\n"); + break; + } + expand(p, INCREG, "\tpushl UR\n\tpushl AR\n"); + expand(p, INCREG, "\tpushl UL\n\tpushl AL\n"); + if (p->n_op == DIV && p->n_type == ULONGLONG) ch = "udiv"; + else if (p->n_op == DIV) ch = "div"; + else if (p->n_op == MOD && p->n_type == ULONGLONG) ch = "umod"; + else if (p->n_op == MOD) ch = "mod"; + else ch = 0, comperr("ZO"); +#ifdef ELFABI + printf("\tcall " EXPREFIX "__%sdi3%s\n\taddl $%d,%s\n", + ch, (kflag ? "@PLT" : ""), pr, rnames[ESP]); +#else + printf("\tcall " EXPREFIX "__%sdi3\n\taddl $%d,%s\n", + ch, pr, rnames[ESP]); +#endif + break; + + case 'P': /* push hidden argument on stack */ + printf("\tleal -%d(%%ebp),", stkpos); + adrput(stdout, getlr(p, '1')); + printf("\n\tpushl "); + adrput(stdout, getlr(p, '1')); + putchar('\n'); + break; + + case 'Q': /* emit struct assign */ + /* + * With <= 16 bytes, put out mov's, otherwise use movsb/w/l. + * esi/edi/ecx are available. + * XXX should not need esi/edi if not rep movsX. + * XXX can save one insn if src ptr in reg. + */ + switch (p->n_stsize) { + case 1: + expand(p, INAREG, " movb (%esi),%cl\n"); + expand(p, INAREG, " movb %cl,AL\n"); + break; + case 2: + expand(p, INAREG, " movw (%esi),%cx\n"); + expand(p, INAREG, " movw %cx,AL\n"); + break; + case 4: + expand(p, INAREG, " movl (%esi),%ecx\n"); + expand(p, INAREG, " movl %ecx,AL\n"); + break; + default: + expand(p, INAREG, " leal AL,%edi\n"); + if (p->n_stsize <= 16 && (p->n_stsize & 3) == 0) { + printf(" movl (%%esi),%%ecx\n"); + printf(" movl %%ecx,(%%edi)\n"); + printf(" movl 4(%%esi),%%ecx\n"); + printf(" movl %%ecx,4(%%edi)\n"); + if (p->n_stsize > 8) { + printf(" movl 8(%%esi),%%ecx\n"); + printf(" movl %%ecx,8(%%edi)\n"); + } + if (p->n_stsize == 16) { + printf("\tmovl 12(%%esi),%%ecx\n"); + printf("\tmovl %%ecx,12(%%edi)\n"); + } + } else { + if (p->n_stsize > 4) { + printf("\tmovl $%d,%%ecx\n", + p->n_stsize >> 2); + printf(" rep movsl\n"); + } + if (p->n_stsize & 2) + printf(" movsw\n"); + if (p->n_stsize & 1) + printf(" movsb\n"); + } + break; + } + break; + + case 'S': /* emit eventual move after cast from longlong */ + pr = DECRA(p->n_reg, 0); + lr = p->n_left->n_rval; + switch (p->n_type) { + case CHAR: + case UCHAR: + if (rnames[pr][2] == 'l' && rnames[lr][2] == 'x' && + rnames[pr][1] == rnames[lr][1]) + break; + if (rnames[lr][2] == 'x') { + printf("\tmovb %%%cl,%s\n", + rnames[lr][1], rnames[pr]); + break; + } + /* Must go via stack */ + s = BITOOR(freetemp(1)); + printf("\tmovl %%e%ci,%d(%%ebp)\n", rnames[lr][1], s); + printf("\tmovb %d(%%ebp),%s\n", s, rnames[pr]); +// comperr("SCONV1 %s->%s", rnames[lr], rnames[pr]); + break; + + case SHORT: + case USHORT: + if (rnames[lr][1] == rnames[pr][2] && + rnames[lr][2] == rnames[pr][3]) + break; + printf("\tmovw %%%c%c,%%%s\n", + rnames[lr][1], rnames[lr][2], rnames[pr]+2); + break; + case INT: + case UNSIGNED: + if (rnames[lr][1] == rnames[pr][2] && + rnames[lr][2] == rnames[pr][3]) + break; + printf("\tmovl %%e%c%c,%s\n", + rnames[lr][1], rnames[lr][2], rnames[pr]); + break; + + default: + if (rnames[lr][1] == rnames[pr][2] && + rnames[lr][2] == rnames[pr][3]) + break; + comperr("SCONV2 %s->%s", rnames[lr], rnames[pr]); + break; + } + break; + + default: + comperr("zzzcode %c", c); + } +} + +/*ARGSUSED*/ +int +rewfld(NODE *p) +{ + return(1); +} + +int canaddr(NODE *); +int +canaddr(NODE *p) +{ + int o = p->n_op; + + if (o==NAME || o==REG || o==ICON || o==OREG || + (o==UMUL && shumul(p->n_left, SOREG))) + return(1); + return(0); +} + +/* + * Does the bitfield shape match? + */ +int +flshape(NODE *p) +{ + int o = p->n_op; + + if (o == OREG || o == REG || o == NAME) + return SRDIR; /* Direct match */ + if (o == UMUL && shumul(p->n_left, SOREG)) + return SROREG; /* Convert into oreg */ + return SRREG; /* put it into a register */ +} + +/* INTEMP shapes must not contain any temporary registers */ +/* XXX should this go away now? */ +int +shtemp(NODE *p) +{ + return 0; +#if 0 + int r; + + if (p->n_op == STARG ) + p = p->n_left; + + switch (p->n_op) { + case REG: + return (!istreg(p->n_rval)); + + case OREG: + r = p->n_rval; + if (R2TEST(r)) { + if (istreg(R2UPK1(r))) + return(0); + r = R2UPK2(r); + } + return (!istreg(r)); + + case UMUL: + p = p->n_left; + return (p->n_op != UMUL && shtemp(p)); + } + + if (optype(p->n_op) != LTYPE) + return(0); + return(1); +#endif +} + +void +adrcon(CONSZ val) +{ + printf("$" CONFMT, val); +} + +void +conput(FILE *fp, NODE *p) +{ + int val = (int)p->n_lval; + + switch (p->n_op) { + case ICON: + if (p->n_name[0] != '\0') { + fprintf(fp, "%s", p->n_name); + if (val) + fprintf(fp, "+%d", val); + } else + fprintf(fp, "%d", val); + return; + + default: + comperr("illegal conput, p %p", p); + } +} + +/*ARGSUSED*/ +void +insput(NODE *p) +{ + comperr("insput"); +} + +/* + * Write out the upper address, like the upper register of a 2-register + * reference, or the next memory location. + */ +void +upput(NODE *p, int size) +{ + + if (p->n_op == FLD) + p = p->n_left; + + size /= SZCHAR; + switch (p->n_op) { + case REG: + fprintf(stdout, "%%%s", &rnames[p->n_rval][3]); + break; + + case NAME: + case OREG: + p->n_lval += size; + adrput(stdout, p); + p->n_lval -= size; + break; + case ICON: + fprintf(stdout, "$" CONFMT, p->n_lval >> 32); + break; + default: + comperr("upput bad op %d size %d", p->n_op, size); + } +} + +void +adrput(FILE *io, NODE *p) +{ + int r; + /* output an address, with offsets, from p */ + + if (p->n_op == FLD) + p = p->n_left; + + switch (p->n_op) { + + case NAME: + if (p->n_name[0] != '\0') { + fputs(p->n_name, io); + if (p->n_lval != 0) + fprintf(io, "+" CONFMT, p->n_lval); + } else + fprintf(io, CONFMT, p->n_lval); + return; + + case OREG: + r = p->n_rval; + if (p->n_name[0]) + printf("%s%s", p->n_name, p->n_lval ? "+" : ""); + if (p->n_lval) + fprintf(io, "%d", (int)p->n_lval); + if (R2TEST(r)) { + fprintf(io, "(%s,%s,4)", rnames[R2UPK1(r)], + rnames[R2UPK2(r)]); + } else + fprintf(io, "(%s)", rnames[p->n_rval]); + return; + case ICON: +#ifdef PCC_DEBUG + /* Sanitycheck for PIC, to catch adressable constants */ + if (kflag && p->n_name[0] && 0) { + static int foo; + + if (foo++ == 0) { + printf("\nfailing...\n"); + fwalk(p, e2print, 0); + comperr("pass2 conput"); + } + } +#endif + /* addressable value of the constant */ + fputc('$', io); + conput(io, p); + return; + + case REG: + switch (p->n_type) { + case LONGLONG: + case ULONGLONG: + fprintf(io, "%%%c%c%c", rnames[p->n_rval][0], + rnames[p->n_rval][1], rnames[p->n_rval][2]); + break; + case SHORT: + case USHORT: + fprintf(io, "%%%s", &rnames[p->n_rval][2]); + break; + default: + fprintf(io, "%s", rnames[p->n_rval]); + } + return; + + default: + comperr("illegal address, op %d, node %p", p->n_op, p); + return; + + } +} + +static char * +ccbranches[] = { + "je", /* jumpe */ + "jne", /* jumpn */ + "jle", /* jumple */ + "jl", /* jumpl */ + "jge", /* jumpge */ + "jg", /* jumpg */ + "jbe", /* jumple (jlequ) */ + "jb", /* jumpl (jlssu) */ + "jae", /* jumpge (jgequ) */ + "ja", /* jumpg (jgtru) */ +}; + + +/* printf conditional and unconditional branches */ +void +cbgen(int o, int lab) +{ + if (o < EQ || o > UGT) + comperr("bad conditional branch: %s", opst[o]); + printf(" %s " LABFMT "\n", ccbranches[o-EQ], lab); +} + +static void +fixcalls(NODE *p, void *arg) +{ + /* Prepare for struct return by allocating bounce space on stack */ + switch (p->n_op) { + case STCALL: + case USTCALL: + if (p->n_stsize+p2autooff > stkpos) + stkpos = p->n_stsize+p2autooff; + break; + case LS: + case RS: + if (p->n_type != LONGLONG && p->n_type != ULONGLONG) + break; + if (p->n_right->n_op == ICON) /* constants must be char */ + p->n_right->n_type = CHAR; + break; + } +} + +/* + * Must store floats in memory if there are two function calls involved. + */ +static int +storefloat(struct interpass *ip, NODE *p) +{ + int l, r; + + switch (optype(p->n_op)) { + case BITYPE: + l = storefloat(ip, p->n_left); + r = storefloat(ip, p->n_right); + if (p->n_op == CM) + return 0; /* arguments, don't care */ + if (callop(p->n_op)) + return 1; /* found one */ +#define ISF(p) ((p)->n_type == FLOAT || (p)->n_type == DOUBLE || \ + (p)->n_type == LDOUBLE) + if (ISF(p->n_left) && ISF(p->n_right) && l && r) { + /* must store one. store left */ + struct interpass *nip; + TWORD t = p->n_left->n_type; + NODE *ll; + int off; + + off = BITOOR(freetemp(szty(t))); + ll = mklnode(OREG, off, FPREG, t); + nip = ipnode(mkbinode(ASSIGN, ll, p->n_left, t)); + p->n_left = mklnode(OREG, off, FPREG, t); + DLIST_INSERT_BEFORE(ip, nip, qelem); + } + return l|r; + + case UTYPE: + l = storefloat(ip, p->n_left); + if (callop(p->n_op)) + l = 1; + return l; + default: + return 0; + } +} + +static void +outfargs(struct interpass *ip, NODE **ary, int num, int *cwp, int c) +{ + struct interpass *ip2; + NODE *q, *r; + int i; + + for (i = 0; i < num; i++) + if (XASMVAL(cwp[i]) == c && (cwp[i] & (XASMASG|XASMINOUT))) + break; + if (i == num) + return; + q = ary[i]->n_left; + r = mklnode(REG, 0, c == 'u' ? 040 : 037, q->n_type); + ary[i]->n_left = tcopy(r); + ip2 = ipnode(mkbinode(ASSIGN, q, r, q->n_type)); + DLIST_INSERT_AFTER(ip, ip2, qelem); +} + +static void +infargs(struct interpass *ip, NODE **ary, int num, int *cwp, int c) +{ + struct interpass *ip2; + NODE *q, *r; + int i; + + for (i = 0; i < num; i++) + if (XASMVAL(cwp[i]) == c && (cwp[i] & XASMASG) == 0) + break; + if (i == num) + return; + q = ary[i]->n_left; + q = (cwp[i] & XASMINOUT) ? tcopy(q) : q; + r = mklnode(REG, 0, c == 'u' ? 040 : 037, q->n_type); + if ((cwp[i] & XASMINOUT) == 0) + ary[i]->n_left = tcopy(r); + ip2 = ipnode(mkbinode(ASSIGN, r, q, q->n_type)); + DLIST_INSERT_BEFORE(ip, ip2, qelem); +} + +/* + * Extract float args to XASM and ensure that they are put on the stack + * in correct order. + * This should be done sow other way. + */ +static void +fixxfloat(struct interpass *ip, NODE *p) +{ + NODE *w, **ary; + int nn, i, c, *cwp; + + nn = 1; + w = p->n_left; + if (w->n_op == ICON && w->n_type == STRTY) + return; + /* index all xasm args first */ + for (; w->n_op == CM; w = w->n_left) + nn++; + ary = tmpcalloc(nn * sizeof(NODE *)); + cwp = tmpcalloc(nn * sizeof(int)); + for (i = 0, w = p->n_left; w->n_op == CM; w = w->n_left) { + ary[i] = w->n_right; + cwp[i] = xasmcode(ary[i]->n_name); + i++; + } + ary[i] = w; + cwp[i] = xasmcode(ary[i]->n_name); + for (i = 0; i < nn; i++) + if (XASMVAL(cwp[i]) == 't' || XASMVAL(cwp[i]) == 'u') + break; + if (i == nn) + return; + + for (i = 0; i < nn; i++) { + c = XASMVAL(cwp[i]); + if (c >= '0' && c <= '9') + cwp[i] = (cwp[i] & ~0377) | XASMVAL(cwp[c-'0']); + } + infargs(ip, ary, nn, cwp, 'u'); + infargs(ip, ary, nn, cwp, 't'); + outfargs(ip, ary, nn, cwp, 't'); + outfargs(ip, ary, nn, cwp, 'u'); +} + +void +myreader(struct interpass *ipole) +{ + struct interpass *ip; + + stkpos = p2autooff; + DLIST_FOREACH(ip, ipole, qelem) { + if (ip->type != IP_NODE) + continue; + walkf(ip->ip_node, fixcalls, 0); + storefloat(ip, ip->ip_node); + if (ip->ip_node->n_op == XASM) + fixxfloat(ip, ip->ip_node); + } + if (stkpos > p2autooff) + p2autooff = stkpos; + if (stkpos > p2maxautooff) + p2maxautooff = stkpos; + if (x2debug) + printip(ipole); +} + +/* + * Remove some PCONVs after OREGs are created. + */ +static void +pconv2(NODE *p, void *arg) +{ + NODE *q; + + if (p->n_op == PLUS) { + if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) { + if (p->n_right->n_op != ICON) + return; + if (p->n_left->n_op != PCONV) + return; + if (p->n_left->n_left->n_op != OREG) + return; + q = p->n_left->n_left; + nfree(p->n_left); + p->n_left = q; + /* + * This will be converted to another OREG later. + */ + } + } +} + +void +mycanon(NODE *p) +{ + walkf(p, pconv2, 0); +} + +void +myoptim(struct interpass *ip) +{ +} + +static char rl[] = + { EAX, EAX, EAX, EAX, EAX, EDX, EDX, EDX, EDX, ECX, ECX, ECX, EBX, EBX, ESI }; +static char rh[] = + { EDX, ECX, EBX, ESI, EDI, ECX, EBX, ESI, EDI, EBX, ESI, EDI, ESI, EDI, EDI }; + +void +rmove(int s, int d, TWORD t) +{ + int sl, sh, dl, dh; + + switch (t) { + case LONGLONG: + case ULONGLONG: +#if 1 + sl = rl[s-EAXEDX]; + sh = rh[s-EAXEDX]; + dl = rl[d-EAXEDX]; + dh = rh[d-EAXEDX]; + + /* sanity checks, remove when satisfied */ + if (memcmp(rnames[s], rnames[sl]+1, 3) != 0 || + memcmp(rnames[s]+3, rnames[sh]+1, 3) != 0) + comperr("rmove source error"); + if (memcmp(rnames[d], rnames[dl]+1, 3) != 0 || + memcmp(rnames[d]+3, rnames[dh]+1, 3) != 0) + comperr("rmove dest error"); +#define SW(x,y) { int i = x; x = y; y = i; } + if (sh == dl) { + /* Swap if overwriting */ + SW(sl, sh); + SW(dl, dh); + } + if (sl != dl) + printf(" movl %s,%s\n", rnames[sl], rnames[dl]); + if (sh != dh) + printf(" movl %s,%s\n", rnames[sh], rnames[dh]); +#else + if (memcmp(rnames[s], rnames[d], 3) != 0) + printf(" movl %%%c%c%c,%%%c%c%c\n", + rnames[s][0],rnames[s][1],rnames[s][2], + rnames[d][0],rnames[d][1],rnames[d][2]); + if (memcmp(&rnames[s][3], &rnames[d][3], 3) != 0) + printf(" movl %%%c%c%c,%%%c%c%c\n", + rnames[s][3],rnames[s][4],rnames[s][5], + rnames[d][3],rnames[d][4],rnames[d][5]); +#endif + break; + case CHAR: + case UCHAR: + printf(" movb %s,%s\n", rnames[s], rnames[d]); + break; + case FLOAT: + case DOUBLE: + case LDOUBLE: +#ifdef notdef + /* a=b()*c(); will generate this */ + comperr("bad float rmove: %d %d", s, d); +#endif + break; + default: + printf(" movl %s,%s\n", rnames[s], rnames[d]); + } +} + +/* + * For class c, find worst-case displacement of the number of + * registers in the array r[] indexed by class. + */ +int +COLORMAP(int c, int *r) +{ + int num; + + switch (c) { + case CLASSA: + num = r[CLASSB] > 4 ? 4 : r[CLASSB]; + num += 2*r[CLASSC]; + num += r[CLASSA]; + return num < 6; + case CLASSB: + num = r[CLASSA]; + num += 2*r[CLASSC]; + num += r[CLASSB]; + return num < 4; + case CLASSC: + num = r[CLASSA]; + num += r[CLASSB] > 4 ? 4 : r[CLASSB]; + num += 2*r[CLASSC]; + return num < 5; + case CLASSD: + return r[CLASSD] < DREGCNT; + } + return 0; /* XXX gcc */ +} + +char *rnames[] = { + "%eax", "%edx", "%ecx", "%ebx", "%esi", "%edi", "%ebp", "%esp", + "%al", "%ah", "%dl", "%dh", "%cl", "%ch", "%bl", "%bh", + "eaxedx", "eaxecx", "eaxebx", "eaxesi", "eaxedi", "edxecx", + "edxebx", "edxesi", "edxedi", "ecxebx", "ecxesi", "ecxedi", + "ebxesi", "ebxedi", "esiedi", + "%st0", "%st1", "%st2", "%st3", "%st4", "%st5", "%st6", "%st7", +}; + +/* + * Return a class suitable for a specific type. + */ +int +gclass(TWORD t) +{ + if (t == CHAR || t == UCHAR) + return CLASSB; + if (t == LONGLONG || t == ULONGLONG) + return CLASSC; + if (t == FLOAT || t == DOUBLE || t == LDOUBLE) + return CLASSD; + return CLASSA; +} + +/* + * Calculate argument sizes. + */ +void +lastcall(NODE *p) +{ + NODE *op = p; + int size = 0; + + p->n_qual = 0; + if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL) + return; + for (p = p->n_right; p->n_op == CM; p = p->n_left) + size += argsiz(p->n_right); + size += argsiz(p); +#if defined(ELFABI) + if (kflag) + size -= 4; +#endif + + +#if defined(MACHOABI) + int newsize = (size + 15) & ~15; /* stack alignment */ + int align = newsize-size; + + if (align != 0) + printf(" subl $%d,%%esp\n", align); + + size=newsize; +#endif + + op->n_qual = size; /* XXX */ +} + +/* + * Special shapes. + */ +int +special(NODE *p, int shape) +{ + int o = p->n_op; + + switch (shape) { + case SFUNCALL: + if (o == STCALL || o == USTCALL) + return SRREG; + break; + case SPCON: + if (o != ICON || p->n_name[0] || + p->n_lval < 0 || p->n_lval > 0x7fffffff) + break; + return SRDIR; + case SMIXOR: + return tshape(p, SZERO); + case SMILWXOR: + if (o != ICON || p->n_name[0] || + p->n_lval == 0 || p->n_lval & 0xffffffff) + break; + return SRDIR; + case SMIHWXOR: + if (o != ICON || p->n_name[0] || + p->n_lval == 0 || (p->n_lval >> 32) != 0) + break; + return SRDIR; + } + return SRNOPE; +} + +/* + * Target-dependent command-line options. + */ +void +mflags(char *str) +{ +} + +/* + * Do something target-dependent for xasm arguments. + */ +int +myxasm(struct interpass *ip, NODE *p) +{ + struct interpass *ip2; + int Cmax[] = { 31, 63, 127, 0xffff, 3, 255 }; + NODE *in = 0, *ut = 0; + TWORD t; + char *w; + int reg; + int c, cw, v; + + cw = xasmcode(p->n_name); + if (cw & (XASMASG|XASMINOUT)) + ut = p->n_left; + if ((cw & XASMASG) == 0) + in = p->n_left; + + c = XASMVAL(cw); + switch (c) { + case 'D': reg = EDI; break; + case 'S': reg = ESI; break; + case 'a': reg = EAX; break; + case 'b': reg = EBX; break; + case 'c': reg = ECX; break; + case 'd': reg = EDX; break; + + case 't': + case 'u': + p->n_name = tmpstrdup(p->n_name); + w = strchr(p->n_name, XASMVAL(cw)); + *w = 'r'; /* now reg */ + return 1; + + case 'A': reg = EAXEDX; break; + case 'q': { + /* Set edges in MYSETXARG */ + if (p->n_left->n_op == REG || p->n_left->n_op == TEMP) + return 1; + t = p->n_left->n_type; + if (in && ut) + in = tcopy(in); + p->n_left = mklnode(TEMP, 0, p2env.epp->ip_tmpnum++, t); + if (ut) { + ip2 = ipnode(mkbinode(ASSIGN, ut, tcopy(p->n_left), t)); + DLIST_INSERT_AFTER(ip, ip2, qelem); + } + if (in) { + ip2 = ipnode(mkbinode(ASSIGN, tcopy(p->n_left), in, t)); + DLIST_INSERT_BEFORE(ip, ip2, qelem); + } + return 1; + } + + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + if (p->n_left->n_op != ICON) + uerror("xasm arg not constant"); + v = p->n_left->n_lval; + if ((c == 'K' && v < -128) || + (c == 'L' && v != 0xff && v != 0xffff) || + (c != 'K' && v < 0) || + (v > Cmax[c-'I'])) + uerror("xasm val out of range"); + p->n_name = "i"; + return 1; + + default: + return 0; + } + /* If there are requested either memory or register, delete memory */ + w = p->n_name = tmpstrdup(p->n_name); + if (*w == '=') + w++; + *w++ = 'r'; + *w = 0; + + t = p->n_left->n_type; + if (reg == EAXEDX) { + p->n_label = CLASSC; + } else { + p->n_label = CLASSA; + if (t == CHAR || t == UCHAR) { + p->n_label = CLASSB; + reg = reg * 2 + 8; + } + } + if (t == FLOAT || t == DOUBLE || t == LDOUBLE) { + p->n_label = CLASSD; + reg += 037; + } + + if (in && ut) + in = tcopy(in); + p->n_left = mklnode(REG, 0, reg, t); + if (ut) { + ip2 = ipnode(mkbinode(ASSIGN, ut, tcopy(p->n_left), t)); + DLIST_INSERT_AFTER(ip, ip2, qelem); + } + if (in) { + ip2 = ipnode(mkbinode(ASSIGN, tcopy(p->n_left), in, t)); + DLIST_INSERT_BEFORE(ip, ip2, qelem); + } + return 1; +} + +void +targarg(char *w, void *arg) +{ + NODE **ary = arg; + NODE *p, *q; + + if (ary[(int)w[1]-'0'] == 0) + p = ary[(int)w[1]-'0'-1]->n_left; /* XXX */ + else + p = ary[(int)w[1]-'0']->n_left; + if (optype(p->n_op) != LTYPE) + comperr("bad xarg op %d", p->n_op); + q = tcopy(p); + if (q->n_op == REG) { + if (*w == 'k') { + q->n_type = INT; + } else if (*w != 'w') { + if (q->n_type > UCHAR) { + regno(q) = regno(q)*2+8; + if (*w == 'h') + regno(q)++; + } + q->n_type = INT; + } else + q->n_type = SHORT; + } + adrput(stdout, q); + tfree(q); +} + +/* + * target-specific conversion of numeric arguments. + */ +int +numconv(void *ip, void *p1, void *q1) +{ + NODE *p = p1, *q = q1; + int cw = xasmcode(q->n_name); + + switch (XASMVAL(cw)) { + case 'a': + case 'b': + case 'c': + case 'd': + p->n_name = tmpcalloc(2); + p->n_name[0] = (char)XASMVAL(cw); + return 1; + default: + return 0; + } +} + +static struct { + char *name; int num; +} xcr[] = { + { "eax", EAX }, + { "ebx", EBX }, + { "ecx", ECX }, + { "edx", EDX }, + { "esi", ESI }, + { "edi", EDI }, + { "ax", EAX }, + { "bx", EBX }, + { "cx", ECX }, + { "dx", EDX }, + { NULL, 0 }, +}; + +/* + * Check for other names of the xasm constraints registers. + */ + +/* + * Check for other names of the xasm constraints registers. + */ +int xasmconstregs(char *s) +{ + int i; + + if (strncmp(s, "st", 2) == 0) { + int off =0; + if (s[2] == '(' && s[4] == ')') + off = s[3] - '0'; + return ESIEDI + 1 + off; + } + + for (i = 0; xcr[i].name; i++) + if (strcmp(xcr[i].name, s) == 0) + return xcr[i].num; + return -1; +} + diff --git a/compilers/pcc/pcc-1.0.0/arch/i386/macdefs.h b/compilers/pcc/pcc-1.0.0/arch/i386/macdefs.h new file mode 100644 index 00000000..46345158 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/i386/macdefs.h @@ -0,0 +1,374 @@ +/* $Id: macdefs.h,v 1.77 2011/02/04 15:08:58 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Machine-dependent defines for both passes. + */ + +/* + * Convert (multi-)character constant to integer. + */ +#define makecc(val,i) lastcon = (lastcon<<8)|((val<<24)>>24); + +#define ARGINIT 64 /* # bits above fp where arguments start */ +#define AUTOINIT 0 /* # bits below fp where automatics start */ + +/* + * Storage space requirements + */ +#define SZCHAR 8 +#define SZBOOL 8 +#define SZINT 32 +#define SZFLOAT 32 +#define SZDOUBLE 64 +#ifdef MACHOABI +#define SZLDOUBLE 128 +#else +#define SZLDOUBLE 96 +#endif +#define SZLONG 32 +#define SZSHORT 16 +#define SZLONGLONG 64 +#define SZPOINT(t) 32 + +/* + * Alignment constraints + */ +#define ALCHAR 8 +#define ALBOOL 8 +#define ALINT 32 +#define ALFLOAT 32 +#define ALDOUBLE 32 +#ifdef MACHOABI +#define ALLDOUBLE 128 +#else +#define ALLDOUBLE 32 +#endif +#define ALLONG 32 +#define ALLONGLONG 32 +#define ALSHORT 16 +#define ALPOINT 32 +#undef ALSTRUCT /* Not defined if ELF ABI */ +#define ALSTACK 32 +#define ALMAX 128 /* not yet supported type */ + +/* + * Min/max values. + */ +#define MIN_CHAR -128 +#define MAX_CHAR 127 +#define MAX_UCHAR 255 +#define MIN_SHORT -32768 +#define MAX_SHORT 32767 +#define MAX_USHORT 65535 +#define MIN_INT (-0x7fffffff-1) +#define MAX_INT 0x7fffffff +#define MAX_UNSIGNED 0xffffffff +#define MIN_LONG MIN_INT +#define MAX_LONG MAX_INT +#define MAX_ULONG MAX_UNSIGNED +#define MIN_LONGLONG 0x8000000000000000LL +#define MAX_LONGLONG 0x7fffffffffffffffLL +#define MAX_ULONGLONG 0xffffffffffffffffULL + +/* Default char is signed */ +#undef CHAR_UNSIGNED +#define BOOL_TYPE CHAR /* what used to store _Bool */ + +/* + * Use large-enough types. + */ +typedef long long CONSZ; +typedef unsigned long long U_CONSZ; +typedef long long OFFSZ; + +#define CONFMT "%lld" /* format for printing constants */ +#if defined(ELFABI) +#define LABFMT ".L%d" /* format for printing labels */ +#define STABLBL ".LL%d" /* format for stab (debugging) labels */ +#else +#define LABFMT "L%d" /* format for printing labels */ +#define STABLBL "LL%d" /* format for stab (debugging) labels */ +#endif +#ifdef LANG_F77 +#define BLANKCOMMON "_BLNK_" +#define MSKIREG (M(TYSHORT)|M(TYLONG)) +#define TYIREG TYLONG +#define FSZLENG FSZLONG +#define AUTOREG EBP +#define ARGREG EBP +#define ARGOFFSET 8 +#endif + +#ifdef MACHOABI +#define STAB_LINE_ABSOLUTE /* S_LINE fields use absolute addresses */ +#endif + +#define BACKAUTO /* stack grows negatively for automatics */ +#define BACKTEMP /* stack grows negatively for temporaries */ + +#undef FIELDOPS /* no bit-field instructions */ +#define RTOLBYTES /* bytes are numbered right to left */ + +#define ENUMSIZE(high,low) INT /* enums are always stored in full int */ + +#define FINDMOPS /* i386 has instructions that modifies memory */ +#define CC_DIV_0 /* division by zero is safe in the compiler */ + +/* Definitions mostly used in pass2 */ + +#define BYTEOFF(x) ((x)&03) +#define wdal(k) (BYTEOFF(k)==0) +#define BITOOR(x) (x) /* bit offset to oreg offset XXX die! */ + +#define STOARG(p) +#define STOFARG(p) +#define STOSTARG(p) +#define genfcall(a,b) gencall(a,b) + +#define szty(t) (((t) == DOUBLE || (t) == FLOAT || \ + (t) == LONGLONG || (t) == ULONGLONG) ? 2 : (t) == LDOUBLE ? 3 : 1) + +/* + * The x86 has a bunch of register classes, most of them interfering + * with each other. All registers are given a sequential number to + * identify it which must match rnames[] in local2.c. + * Class membership and overlaps are defined in the macros RSTATUS + * and ROVERLAP below. + * + * The classes used on x86 are: + * A - short and int regs + * B - char regs + * C - long long regs + * D - floating point + */ +#define EAX 000 /* Scratch and return register */ +#define EDX 001 /* Scratch and secondary return register */ +#define ECX 002 /* Scratch (and shift count) register */ +#define EBX 003 /* GDT pointer or callee-saved temporary register */ +#define ESI 004 /* Callee-saved temporary register */ +#define EDI 005 /* Callee-saved temporary register */ +#define EBP 006 /* Frame pointer */ +#define ESP 007 /* Stack pointer */ + +#define AL 010 +#define AH 011 +#define DL 012 +#define DH 013 +#define CL 014 +#define CH 015 +#define BL 016 +#define BH 017 + +#define EAXEDX 020 +#define EAXECX 021 +#define EAXEBX 022 +#define EAXESI 023 +#define EAXEDI 024 +#define EDXECX 025 +#define EDXEBX 026 +#define EDXESI 027 +#define EDXEDI 030 +#define ECXEBX 031 +#define ECXESI 032 +#define ECXEDI 033 +#define EBXESI 034 +#define EBXEDI 035 +#define ESIEDI 036 + +/* The 8 math registers in class D lacks names */ + +#define MAXREGS 047 /* 39 registers */ + +#define RSTATUS \ + SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|PERMREG, \ + SAREG|PERMREG, SAREG|PERMREG, 0, 0, \ + SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \ + SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \ + SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \ + SDREG, SDREG, SDREG, SDREG, SDREG, SDREG, SDREG, SDREG, + +#define ROVERLAP \ + /* 8 basic registers */\ + { AL, AH, EAXEDX, EAXECX, EAXEBX, EAXESI, EAXEDI, -1 },\ + { DL, DH, EAXEDX, EDXECX, EDXEBX, EDXESI, EDXEDI, -1 },\ + { CL, CH, EAXECX, EDXECX, ECXEBX, ECXESI, ECXEDI, -1 },\ + { BL, BH, EAXEBX, EDXEBX, ECXEBX, EBXESI, EBXEDI, -1 },\ + { EAXESI, EDXESI, ECXESI, EBXESI, ESIEDI, -1 },\ + { EAXEDI, EDXEDI, ECXEDI, EBXEDI, ESIEDI, -1 },\ + { -1 },\ + { -1 },\ +\ + /* 8 char registers */\ + { EAX, EAXEDX, EAXECX, EAXEBX, EAXESI, EAXEDI, -1 },\ + { EAX, EAXEDX, EAXECX, EAXEBX, EAXESI, EAXEDI, -1 },\ + { EDX, EAXEDX, EDXECX, EDXEBX, EDXESI, EDXEDI, -1 },\ + { EDX, EAXEDX, EDXECX, EDXEBX, EDXESI, EDXEDI, -1 },\ + { ECX, EAXECX, EDXECX, ECXEBX, ECXESI, ECXEDI, -1 },\ + { ECX, EAXECX, EDXECX, ECXEBX, ECXESI, ECXEDI, -1 },\ + { EBX, EAXEBX, EDXEBX, ECXEBX, EBXESI, EBXEDI, -1 },\ + { EBX, EAXEBX, EDXEBX, ECXEBX, EBXESI, EBXEDI, -1 },\ +\ + /* 15 long-long-emulating registers */\ + { EAX, AL, AH, EDX, DL, DH, EAXECX, EAXEBX, EAXESI, /* eaxedx */\ + EAXEDI, EDXECX, EDXEBX, EDXESI, EDXEDI, -1, },\ + { EAX, AL, AH, ECX, CL, CH, EAXEDX, EAXEBX, EAXESI, /* eaxecx */\ + EAXEDI, EDXECX, ECXEBX, ECXESI, ECXEDI, -1 },\ + { EAX, AL, AH, EBX, BL, BH, EAXEDX, EAXECX, EAXESI, /* eaxebx */\ + EAXEDI, EDXEBX, ECXEBX, EBXESI, EBXEDI, -1 },\ + { EAX, AL, AH, ESI, EAXEDX, EAXECX, EAXEBX, EAXEDI, /* eaxesi */\ + EDXESI, ECXESI, EBXESI, ESIEDI, -1 },\ + { EAX, AL, AH, EDI, EAXEDX, EAXECX, EAXEBX, EAXESI, /* eaxedi */\ + EDXEDI, ECXEDI, EBXEDI, ESIEDI, -1 },\ + { EDX, DL, DH, ECX, CL, CH, EAXEDX, EAXECX, EDXEBX, /* edxecx */\ + EDXESI, EDXEDI, ECXEBX, ECXESI, ECXEDI, -1 },\ + { EDX, DL, DH, EBX, BL, BH, EAXEDX, EDXECX, EDXESI, /* edxebx */\ + EDXEDI, EAXEBX, ECXEBX, EBXESI, EBXEDI, -1 },\ + { EDX, DL, DH, ESI, EAXEDX, EDXECX, EDXEBX, EDXEDI, /* edxesi */\ + EAXESI, ECXESI, EBXESI, ESIEDI, -1 },\ + { EDX, DL, DH, EDI, EAXEDX, EDXECX, EDXEBX, EDXESI, /* edxedi */\ + EAXEDI, ECXEDI, EBXEDI, ESIEDI, -1 },\ + { ECX, CL, CH, EBX, BL, BH, EAXECX, EDXECX, ECXESI, /* ecxebx */\ + ECXEDI, EAXEBX, EDXEBX, EBXESI, EBXEDI, -1 },\ + { ECX, CL, CH, ESI, EAXECX, EDXECX, ECXEBX, ECXEDI, /* ecxesi */\ + EAXESI, EDXESI, EBXESI, ESIEDI, -1 },\ + { ECX, CL, CH, EDI, EAXECX, EDXECX, ECXEBX, ECXESI, /* ecxedi */\ + EAXEDI, EDXEDI, EBXEDI, ESIEDI, -1 },\ + { EBX, BL, BH, ESI, EAXEBX, EDXEBX, ECXEBX, EBXEDI, /* ebxesi */\ + EAXESI, EDXESI, ECXESI, ESIEDI, -1 },\ + { EBX, BL, BH, EDI, EAXEBX, EDXEBX, ECXEBX, EBXESI, /* ebxedi */\ + EAXEDI, EDXEDI, ECXEDI, ESIEDI, -1 },\ + { ESI, EDI, EAXESI, EDXESI, ECXESI, EBXESI, /* esiedi */\ + EAXEDI, EDXEDI, ECXEDI, EBXEDI, -1 },\ +\ + /* The fp registers do not overlap with anything */\ + { -1 },\ + { -1 },\ + { -1 },\ + { -1 },\ + { -1 },\ + { -1 },\ + { -1 },\ + { -1 }, + + +/* Return a register class based on the type of the node */ +#define PCLASS(p) (p->n_type <= UCHAR ? SBREG : \ + (p->n_type == LONGLONG || p->n_type == ULONGLONG ? SCREG : \ + (p->n_type >= FLOAT && p->n_type <= LDOUBLE ? SDREG : SAREG))) + +#define NUMCLASS 4 /* highest number of reg classes used */ + +int COLORMAP(int c, int *r); +#define GCLASS(x) (x < 8 ? CLASSA : x < 16 ? CLASSB : x < 31 ? CLASSC : CLASSD) +#define DECRA(x,y) (((x) >> (y*6)) & 63) /* decode encoded regs */ +#define ENCRD(x) (x) /* Encode dest reg in n_reg */ +#define ENCRA1(x) ((x) << 6) /* A1 */ +#define ENCRA2(x) ((x) << 12) /* A2 */ +#define ENCRA(x,y) ((x) << (6+y*6)) /* encode regs in int */ +/* XXX - return char in al? */ +#define RETREG(x) (x == CHAR || x == UCHAR ? AL : \ + x == LONGLONG || x == ULONGLONG ? EAXEDX : \ + x == FLOAT || x == DOUBLE || x == LDOUBLE ? 31 : EAX) + +#if 0 +#define R2REGS 1 /* permit double indexing */ +#endif + +/* XXX - to die */ +#define FPREG EBP /* frame pointer */ +#define STKREG ESP /* stack pointer */ + +#define SHSTR (MAXSPECIAL+1) /* short struct */ +#define SFUNCALL (MAXSPECIAL+2) /* struct assign after function call */ +#define SPCON (MAXSPECIAL+3) /* positive nonnamed constant */ + +/* + * Specials that indicate the applicability of machine idioms. + */ +#define SMIXOR (MAXSPECIAL+4) +#define SMILWXOR (MAXSPECIAL+5) +#define SMIHWXOR (MAXSPECIAL+6) + +/* + * i386-specific symbol table flags. + */ +#define SSECTION SLOCAL1 +#define STLS SLOCAL2 +#define SSTDCALL SLOCAL2 +#define SDLLINDIRECT SLOCAL3 + +/* + * i386-specific node flags. + */ +#define FSTDCALL NLOCAL1 +#define FFPPOP NLOCAL2 + +/* + * i386-specific interpass stuff. + */ + +#define TARGET_IPP_MEMBERS \ + int ipp_argstacksize; + +/* + * Extended assembler macros. + */ +void targarg(char *w, void *arg); +#define XASM_TARGARG(w, ary) \ + (w[1] == 'b' || w[1] == 'h' || w[1] == 'w' || w[1] == 'k' ? \ + w++, targarg(w, ary), 1 : 0) +int numconv(void *ip, void *p, void *q); +#define XASM_NUMCONV(ip, p, q) numconv(ip, p, q) +int xasmconstregs(char *); +#define XASMCONSTREGS(x) xasmconstregs(x) +#define MYSETXARG if (XASMVAL(cw) == 'q') { \ + c = 'r'; addalledges(&ablock[ESI]); addalledges(&ablock[EDI]); } + +/* + * builtins. + */ +#define TARGET_BUILTINS \ + { "__builtin_frame_address", i386_builtin_frame_address, -1 }, \ + { "__builtin_return_address", i386_builtin_return_address, -1 }, + +#define NODE struct node +struct node; +NODE *i386_builtin_frame_address(NODE *f, NODE *a, unsigned int); +NODE *i386_builtin_return_address(NODE *f, NODE *a, unsigned int); +#undef NODE + +#if defined(MACHOABI) +struct stub { + struct { struct stub *q_forw, *q_back; } link; + char *name; +}; +extern struct stub stublist; +extern struct stub nlplist; +void addstub(struct stub *list, char *name); +#endif diff --git a/compilers/pcc/pcc-1.0.0/arch/i386/order.c b/compilers/pcc/pcc-1.0.0/arch/i386/order.c new file mode 100644 index 00000000..7c174ad6 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/i386/order.c @@ -0,0 +1,313 @@ +/* $Id: order.c,v 1.59 2011/01/29 09:55:29 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass2.h" + +#include + +int canaddr(NODE *); + +/* is it legal to make an OREG or NAME entry which has an + * offset of off, (from a register of r), if the + * resulting thing had type t */ +int +notoff(TWORD t, int r, CONSZ off, char *cp) +{ + return(0); /* YES */ +} + +/* + * Turn a UMUL-referenced node into OREG. + * Be careful about register classes, this is a place where classes change. + */ +void +offstar(NODE *p, int shape) +{ + NODE *r; + + if (x2debug) + printf("offstar(%p)\n", p); + + if (isreg(p)) + return; /* Is already OREG */ + + r = p->n_right; + if( p->n_op == PLUS || p->n_op == MINUS ){ + if( r->n_op == ICON ){ + if (isreg(p->n_left) == 0) + (void)geninsn(p->n_left, INAREG); + /* Converted in ormake() */ + return; + } + if (r->n_op == LS && r->n_right->n_op == ICON && + r->n_right->n_lval == 2 && p->n_op == PLUS) { + if (isreg(p->n_left) == 0) + (void)geninsn(p->n_left, INAREG); + if (isreg(r->n_left) == 0) + (void)geninsn(r->n_left, INAREG); + return; + } + } + (void)geninsn(p, INAREG); +} + +/* + * Do the actual conversion of offstar-found OREGs into real OREGs. + */ +void +myormake(NODE *q) +{ + NODE *p, *r; + + if (x2debug) + printf("myormake(%p)\n", q); + + p = q->n_left; + if (p->n_op == PLUS && (r = p->n_right)->n_op == LS && + r->n_right->n_op == ICON && r->n_right->n_lval == 2 && + p->n_left->n_op == REG && r->n_left->n_op == REG) { + q->n_op = OREG; + q->n_lval = 0; + q->n_rval = R2PACK(p->n_left->n_rval, r->n_left->n_rval, 0); + tfree(p); + } +} + +/* + * Shape matches for UMUL. Cooperates with offstar(). + */ +int +shumul(NODE *p, int shape) +{ + + if (x2debug) + printf("shumul(%p)\n", p); + + /* Turns currently anything into OREG on x86 */ + if (shape & SOREG) + return SROREG; + return SRNOPE; +} + +/* + * Rewrite operations on binary operators (like +, -, etc...). + * Called as a result of table lookup. + */ +int +setbin(NODE *p) +{ + + if (x2debug) + printf("setbin(%p)\n", p); + return 0; + +} + +/* setup for assignment operator */ +int +setasg(NODE *p, int cookie) +{ + if (x2debug) + printf("setasg(%p)\n", p); + return(0); +} + +/* setup for unary operator */ +int +setuni(NODE *p, int cookie) +{ + return 0; +} + +/* + * Special handling of some instruction register allocation. + */ +struct rspecial * +nspecial(struct optab *q) +{ + switch (q->op) { + case OPLOG: + { + static struct rspecial s[] = { { NEVER, EAX }, { 0 } }; + return s; + } + + case STASG: + { + static struct rspecial s[] = { + { NEVER, EDI }, + { NRIGHT, ESI }, { NOLEFT, ESI }, + { NOLEFT, ECX }, { NORIGHT, ECX }, + { NEVER, ECX }, { 0 } }; + return s; + } + + case STARG: + { + static struct rspecial s[] = { + { NEVER, EAX }, { NEVER, EDX }, + { NEVER, ECX }, { 0 } }; + return s; + } + + case SCONV: + if ((q->ltype & (TINT|TUNSIGNED|TSHORT|TUSHORT)) && + q->rtype == (TCHAR|TUCHAR)) { + static struct rspecial s[] = { + { NOLEFT, ESI }, { NOLEFT, EDI }, { 0 } }; + return s; + } else if ((q->ltype & TINT) && + q->rtype == (TLONGLONG|TULONGLONG)) { + static struct rspecial s[] = { + { NLEFT, EAX }, { NRES, EAXEDX }, + { NEVER, EAX }, { NEVER, EDX }, { 0 } }; + return s; + } else if (q->ltype == TSHORT && + q->rtype == (TLONGLONG|TULONGLONG)) { + static struct rspecial s[] = { + { NRES, EAXEDX }, + { NEVER, EAX }, { NEVER, EDX }, { 0 } }; + return s; + } else if (q->ltype == TCHAR && + q->rtype == (TLONGLONG|TULONGLONG)) { + static struct rspecial s[] = { + { NRES, EAXEDX }, + { NEVER, EAX }, { NEVER, EDX }, { 0 } }; + return s; + } + break; + case DIV: + if (q->lshape == SBREG) { + static struct rspecial s[] = { + { NEVER, AL }, { NEVER, AH }, + { NLEFT, AL }, { NRES, AL }, + { NORIGHT, AH }, { NORIGHT, AL }, { 0 } }; + return s; + } else if (q->lshape == SAREG) { + static struct rspecial s[] = { + { NEVER, EAX }, { NEVER, EDX }, + { NLEFT, EAX }, { NRES, EAX }, + { NORIGHT, EDX }, { NORIGHT, EAX }, { 0 } }; + return s; + } else if (q->lshape & SCREG) { + static struct rspecial s[] = { + { NEVER, EAX }, { NEVER, EDX }, + { NEVER, ECX }, { NRES, EAXEDX }, { 0 } }; + return s; + } + break; + case MOD: + if (q->lshape == SBREG) { + static struct rspecial s[] = { + { NEVER, AL }, { NEVER, AH }, + { NLEFT, AL }, { NRES, AH }, + { NORIGHT, AH }, { NORIGHT, AL }, { 0 } }; + return s; + } else if (q->lshape == SAREG) { + static struct rspecial s[] = { + { NEVER, EAX }, { NEVER, EDX }, + { NLEFT, EAX }, { NRES, EDX }, + { NORIGHT, EDX }, { NORIGHT, EAX }, { 0 } }; + return s; + } else if (q->lshape & SCREG) { + static struct rspecial s[] = { + { NEVER, EAX }, { NEVER, EDX }, + { NEVER, ECX }, { NRES, EAXEDX }, { 0 } }; + return s; + } + break; + case MUL: + if (q->lshape == SBREG) { + static struct rspecial s[] = { + { NEVER, AL }, { NEVER, AH }, + { NLEFT, AL }, { NRES, AL }, { 0 } }; + return s; + } else if (q->lshape & SCREG) { + static struct rspecial s[] = { + { NLEFT, EAXEDX }, { NRIGHT, ECXESI }, + { NEVER, ESI }, { NRES, EAXEDX }, { 0 } }; + return s; + } + break; + case LS: + case RS: + if (q->visit & (INAREG|INBREG)) { + static struct rspecial s[] = { + { NRIGHT, CL }, { NOLEFT, ECX }, { 0 } }; + return s; + } else if (q->visit & INCREG) { + static struct rspecial s[] = { + { NLEFT, EAXEDX }, { NRIGHT, CL }, + { NRES, EAXEDX }, { 0 } }; + return s; + } + break; + + default: + break; + } + comperr("nspecial entry %d", q - table); + return 0; /* XXX gcc */ +} + +/* + * Set evaluation order of a binary node if it differs from default. + */ +int +setorder(NODE *p) +{ + return 0; /* nothing differs on x86 */ +} + +/* + * set registers in calling conventions live. + */ +int * +livecall(NODE *p) +{ + static int r[] = { EAX, EBX, -1 }; + int off = 1; + +#ifdef TLS + if (p->n_left->n_op == ICON && + strcmp(p->n_left->n_name, "___tls_get_addr@PLT") == 0) + off--; +#endif + + return kflag ? &r[off] : &r[2]; +} + +/* + * Signal whether the instruction is acceptable for this target. + */ +int +acceptable(struct optab *op) +{ + return 1; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/i386/table.c b/compilers/pcc/pcc-1.0.0/arch/i386/table.c new file mode 100644 index 00000000..1ff9b1e5 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/i386/table.c @@ -0,0 +1,1643 @@ +/* $Id: table.c,v 1.128 2011/01/29 09:55:29 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass2.h" + +# define TLL TLONGLONG|TULONGLONG +# define ANYSIGNED TINT|TLONG|TSHORT|TCHAR +# define ANYUSIGNED TUNSIGNED|TULONG|TUSHORT|TUCHAR +# define ANYFIXED ANYSIGNED|ANYUSIGNED +# define TUWORD TUNSIGNED|TULONG +# define TSWORD TINT|TLONG +# define TWORD TUWORD|TSWORD +#define SHINT SAREG /* short and int */ +#define ININT INAREG +#define SHCH SBREG /* shape for char */ +#define INCH INBREG +#define SHLL SCREG /* shape for long long */ +#define INLL INCREG +#define SHFL SDREG /* shape for float/double */ +#define INFL INDREG /* shape for float/double */ + +struct optab table[] = { +/* First entry must be an empty entry */ +{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", }, + +/* PCONVs are usually not necessary */ +{ PCONV, INAREG, + SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + 0, RLEFT, + "", }, + +/* + * A bunch conversions of integral<->integral types + * There are lots of them, first in table conversions to itself + * and then conversions from each type to the others. + */ + +/* itself to itself, including pointers */ + +/* convert (u)char to (u)char. */ +{ SCONV, INCH, + SHCH, TCHAR|TUCHAR, + SHCH, TCHAR|TUCHAR, + 0, RLEFT, + "", }, + +/* convert pointers to int. */ +{ SCONV, ININT, + SHINT, TPOINT|TWORD, + SANY, TWORD, + 0, RLEFT, + "", }, + +/* convert (u)longlong to (u)longlong. */ +{ SCONV, INLL, + SHLL, TLL, + SHLL, TLL, + 0, RLEFT, + "", }, + +/* convert between float/double/long double. */ +{ SCONV, INFL, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + 0, RLEFT, + "ZI", }, + +/* convert pointers to pointers. */ +{ SCONV, ININT, + SHINT, TPOINT, + SANY, TPOINT, + 0, RLEFT, + "", }, + +/* char to something */ + +/* convert char to (unsigned) short. */ +{ SCONV, ININT, + SBREG|SOREG|SNAME, TCHAR, + SAREG, TSHORT|TUSHORT, + NASL|NAREG, RESC1, + " movsbw AL,A1\n", }, + +/* convert unsigned char to (u)short. */ +{ SCONV, ININT, + SHCH|SOREG|SNAME, TUCHAR, + SAREG, TSHORT|TUSHORT, + NASL|NAREG, RESC1, + " movzbw AL,A1\n", }, + +/* convert signed char to int (or pointer). */ +{ SCONV, ININT, + SHCH|SOREG|SNAME, TCHAR, + SAREG, TWORD|TPOINT, + NASL|NAREG, RESC1, + " movsbl AL,A1\n", }, + +/* convert unsigned char to (u)int. */ +{ SCONV, ININT, + SHCH|SOREG|SNAME, TUCHAR, + SAREG, TWORD, + NASL|NAREG, RESC1, + " movzbl AL,A1\n", }, + +/* convert char to (u)long long */ +{ SCONV, INLL, + SHCH|SOREG|SNAME, TCHAR, + SANY, TLL, + NSPECIAL|NCREG|NCSL, RESC1, + " movsbl AL,%eax\n cltd\n", }, + +/* convert unsigned char to (u)long long */ +{ SCONV, INLL, + SHCH|SOREG|SNAME, TUCHAR, + SANY, TLL, + NCREG|NCSL, RESC1, + " movzbl AL,A1\n xorl U1,U1\n", }, + +/* convert char (in register) to double XXX - use NTEMP */ +{ SCONV, INFL, + SHCH|SOREG|SNAME, TCHAR, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + NAREG|NASL|NDREG, RESC2, + " movsbl AL,A1\n pushl A1\n" + " fildl (%esp)\n addl $4,%esp\n", }, + +/* convert (u)char (in register) to double XXX - use NTEMP */ +{ SCONV, INFL, + SHCH|SOREG|SNAME, TUCHAR, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + NAREG|NASL|NDREG, RESC2, + " movzbl AL,A1\n pushl A1\n" + " fildl (%esp)\n addl $4,%esp\n", }, + +/* short to something */ + +/* convert short (in memory) to char */ +{ SCONV, INCH, + SNAME|SOREG, TSHORT|TUSHORT, + SHCH, TCHAR|TUCHAR, + NBREG|NBSL, RESC1, + " movb AL,A1\n", }, + +/* convert short (in reg) to char. */ +{ SCONV, INCH, + SAREG|SNAME|SOREG, TSHORT|TUSHORT, + SHCH, TCHAR|TUCHAR, + NSPECIAL|NBREG|NBSL, RESC1, + "ZM", }, + +/* convert short to (u)int. */ +{ SCONV, ININT, + SAREG|SOREG|SNAME, TSHORT, + SAREG, TWORD, + NASL|NAREG, RESC1, + " movswl AL,A1\n", }, + +/* convert unsigned short to (u)int. */ +{ SCONV, ININT, + SAREG|SOREG|SNAME, TUSHORT, + SAREG, TWORD, + NASL|NAREG, RESC1, + " movzwl AL,A1\n", }, + +/* convert short to (u)long long */ +{ SCONV, INLL, + SAREG|SOREG|SNAME, TSHORT, + SHLL, TLL, + NSPECIAL|NCREG|NCSL, RESC1, + " movswl AL,%eax\n cltd\n", }, + +/* convert unsigned short to (u)long long */ +{ SCONV, INLL, + SAREG|SOREG|SNAME, TUSHORT, + SHLL, TLL, + NCREG|NCSL, RESC1, + " movzwl AL,A1\n xorl U1,U1\n", }, + +/* convert short (in memory) to float/double */ +{ SCONV, INFL, + SOREG|SNAME, TSHORT, + SDREG, TLDOUBLE|TDOUBLE|TFLOAT, + NDREG, RESC1, + " fild AL\n", }, + +/* convert short (in register) to float/double */ +{ SCONV, INFL, + SAREG, TSHORT, + SDREG, TLDOUBLE|TDOUBLE|TFLOAT, + NTEMP|NDREG, RESC1, + " pushw AL\n fild (%esp)\n addl $2,%esp\n", }, + +/* convert unsigned short to double XXX - use NTEMP */ +{ SCONV, INFL, + SAREG|SOREG|SNAME, TUSHORT, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + NAREG|NASL|NDREG|NTEMP, RESC2, + " movzwl AL,A1\n pushl A1\n" + " fildl (%esp)\n addl $4,%esp\n", }, + +/* int to something */ + +/* convert int to char. This is done when register is loaded */ +{ SCONV, INCH, + SAREG, TWORD|TPOINT, + SANY, TCHAR|TUCHAR, + NSPECIAL|NBREG|NBSL, RESC1, + "ZM", }, + +/* convert int to short. Nothing to do */ +{ SCONV, INAREG, + SAREG, TWORD, + SANY, TSHORT|TUSHORT, + 0, RLEFT, + "", }, + +/* convert signed int to (u)long long */ +{ SCONV, INLL, + SHINT, TSWORD, + SHLL, TLL, + NSPECIAL|NCREG|NCSL, RESC1, + " cltd\n", }, + +/* convert unsigned int to (u)long long */ +{ SCONV, INLL, + SHINT|SOREG|SNAME, TUWORD|TPOINT, + SHLL, TLL, + NCSL|NCREG, RESC1, + " movl AL,A1\n xorl U1,U1\n", }, + +/* convert int (in memory) to double */ +{ SCONV, INFL, + SOREG|SNAME, TWORD, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + NDREG, RESC1, + " fildl AL\n", }, + +/* convert int (in register) to double */ +{ SCONV, INFL, + SAREG, TWORD, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + NTEMP|NDREG, RESC1, + " pushl AL\n fildl (%esp)\n addl $4,%esp\n", }, + +/* long long to something */ + +/* convert (u)long long to (u)char (mem->reg) */ +{ SCONV, INCH, + SOREG|SNAME, TLL, + SANY, TCHAR|TUCHAR, + NBREG|NBSL, RESC1, + " movb AL,A1\n", }, + +/* convert (u)long long to (u)char (reg->reg, hopefully nothing) */ +{ SCONV, INCH, + SHLL, TLL, + SANY, TCHAR|TUCHAR, + NBREG|NBSL, RESC1, + "ZS", }, + +/* convert (u)long long to (u)short (mem->reg) */ +{ SCONV, INAREG, + SOREG|SNAME, TLL, + SAREG, TSHORT|TUSHORT, + NAREG|NASL, RESC1, + " movw AL,A1\n", }, + +/* convert (u)long long to (u)short (reg->reg, hopefully nothing) */ +{ SCONV, INAREG, + SHLL|SOREG|SNAME, TLL, + SAREG, TSHORT|TUSHORT, + NAREG|NASL, RESC1, + "ZS", }, + +/* convert long long to int (mem->reg) */ +{ SCONV, INAREG, + SOREG|SNAME, TLL, + SAREG, TWORD|TPOINT, + NAREG|NASL, RESC1, + " movl AL,A1\n", }, + +/* convert long long to int (reg->reg, hopefully nothing) */ +{ SCONV, INAREG, + SHLL|SOREG|SNAME, TLL, + SAREG, TWORD|TPOINT, + NAREG|NASL, RESC1, + "ZS", }, + +/* convert long long (in memory) to floating */ +{ SCONV, INFL, + SOREG|SNAME, TLONGLONG, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + NDREG, RESC1, + " fildq AL\n", }, + +/* convert long long (in register) to floating */ +{ SCONV, INFL, + SHLL, TLONGLONG, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + NTEMP|NDREG, RESC1, + " pushl UL\n pushl AL\n" + " fildq (%esp)\n addl $8,%esp\n", }, + +/* convert unsigned long long to floating */ +{ SCONV, INFL, + SCREG, TULONGLONG, + SDREG, TLDOUBLE|TDOUBLE|TFLOAT, + NDREG, RESC1, + "ZJ", }, + +/* float to something */ + +#if 0 /* go via int by adding an extra sconv in clocal() */ +/* convert float/double to (u) char. XXX should use NTEMP here */ +{ SCONV, INCH, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + SHCH, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NBREG, RESC1, + " subl $4,%esp\n fistpl (%esp)\n popl A1\n", }, + +/* convert float/double to (u) int/short/char. XXX should use NTEMP here */ +{ SCONV, INCH, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + SHCH, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NCREG, RESC1, + " subl $4,%esp\n fistpl (%esp)\n popl A1\n", }, +#endif + +/* convert float/double to (u)int. XXX should use NTEMP here */ +{ SCONV, INAREG, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + SAREG, TWORD, + NAREG, RESC1, +#ifdef notdef /* Must round down and nothing else */ + " subl $4,%esp\n fistpl (%esp)\n popl A1\n", }, +#else + " subl $12,%esp\n" + " fnstcw (%esp)\n" + " fnstcw 4(%esp)\n" + " movb $12,1(%esp)\n" + " fldcw (%esp)\n" + " fistpl 8(%esp)\n" + " movl 8(%esp),A1\n" + " fldcw 4(%esp)\n" + " addl $12,%esp\n", }, +#endif + +/* convert float/double (in register) to (unsigned) long long */ +/* XXX - unsigned is not handled correct */ +{ SCONV, INLL, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + SHLL, TLONGLONG|TULONGLONG, + NCREG, RESC1, +#ifdef notdef /* Must round down and nothing else */ + " subl $8,%esp\n fistpq (%esp)\n" + " popl A1\n popl U1\n", }, +#else + " subl $16,%esp\n" + " fnstcw (%esp)\n" + " fnstcw 4(%esp)\n" + " movb $12,1(%esp)\n" + " fldcw (%esp)\n" + " fistpq 8(%esp)\n" + " movl 8(%esp),A1\n" + " movl 12(%esp),U1\n" + " fldcw 4(%esp)\n" + " addl $16,%esp\n", }, +#endif + +/* slut sconv */ + +/* + * Subroutine calls. + */ + +{ UCALL, FOREFF, + SCON, TANY, + SANY, TANY, + 0, 0, + " call CL\nZC", }, + +{ CALL, FOREFF, + SCON, TANY, + SANY, TANY, + 0, 0, + " call CL\nZC", }, + +{ UCALL, FOREFF, + SCON, TANY, + SAREG, TWORD|TPOINT, + 0, 0, + " call CL\nZC", }, + +{ CALL, INAREG, + SCON, TANY, + SAREG, TSHORT|TUSHORT|TWORD|TPOINT, + NAREG|NASL, RESC1, /* should be 0 */ + " call CL\nZC", }, + +{ UCALL, INAREG, + SCON, TANY, + SAREG, TSHORT|TUSHORT|TWORD|TPOINT, + NAREG|NASL, RESC1, /* should be 0 */ + " call CL\nZC", }, + +{ CALL, INBREG, + SCON, TANY, + SBREG, TCHAR|TUCHAR, + NBREG, RESC1, /* should be 0 */ + " call CL\nZC", }, + +{ UCALL, INBREG, + SCON, TANY, + SBREG, TCHAR|TUCHAR, + NBREG, RESC1, /* should be 0 */ + " call CL\nZC", }, + +{ CALL, INCREG, + SCON, TANY, + SCREG, TANY, + NCREG|NCSL, RESC1, /* should be 0 */ + " call CL\nZC", }, + +{ UCALL, INCREG, + SCON, TANY, + SCREG, TANY, + NCREG|NCSL, RESC1, /* should be 0 */ + " call CL\nZC", }, + +{ CALL, INDREG, + SCON, TANY, + SDREG, TANY, + NDREG|NDSL, RESC1, /* should be 0 */ + " call CL\nZC", }, + +{ UCALL, INDREG, + SCON, TANY, + SDREG, TANY, + NDREG|NDSL, RESC1, /* should be 0 */ + " call CL\nZC", }, + +{ CALL, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, 0, + " call *AL\nZC", }, + +{ UCALL, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, 0, + " call *AL\nZC", }, + +{ CALL, INAREG, + SAREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + " call *AL\nZC", }, + +{ UCALL, INAREG, + SAREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + " call *AL\nZC", }, + +{ CALL, INBREG, + SAREG, TANY, + SANY, TANY, + NBREG|NBSL, RESC1, /* should be 0 */ + " call *AL\nZC", }, + +{ UCALL, INBREG, + SAREG, TANY, + SANY, TANY, + NBREG|NBSL, RESC1, /* should be 0 */ + " call *AL\nZC", }, + +{ CALL, INCREG, + SAREG, TANY, + SANY, TANY, + NCREG|NCSL, RESC1, /* should be 0 */ + " call *AL\nZC", }, + +{ UCALL, INCREG, + SAREG, TANY, + SANY, TANY, + NCREG|NCSL, RESC1, /* should be 0 */ + " call *AL\nZC", }, + +{ CALL, INDREG, + SAREG, TANY, + SANY, TANY, + NDREG|NDSL, RESC1, /* should be 0 */ + " call *AL\nZC", }, + +{ UCALL, INDREG, + SAREG, TANY, + SANY, TANY, + NDREG|NDSL, RESC1, /* should be 0 */ + " call *AL\nZC", }, + +/* struct return */ +{ USTCALL, FOREFF, + SCON, TANY, + SANY, TANY, + NAREG|NASL, 0, + "ZP call CL\nZC", }, + +{ USTCALL, INAREG, + SCON, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + "ZP call CL\nZC", }, + +{ USTCALL, INAREG, + SNAME|SAREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + "ZP call *AL\nZC", }, + +{ STCALL, FOREFF, + SCON, TANY, + SANY, TANY, + NAREG|NASL, 0, + "ZP call CL\nZC", }, + +{ STCALL, INAREG, + SCON, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + "ZP call CL\nZC", }, + +{ STCALL, INAREG, + SNAME|SAREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + "ZP call *AL\nZC", }, + +/* + * The next rules handle all binop-style operators. + */ +/* Special treatment for long long */ +{ PLUS, INLL|FOREFF, + SHLL, TLL, + SHLL|SNAME|SOREG, TLL, + 0, RLEFT, + " addl AR,AL\n adcl UR,UL\n", }, + +{ PLUS, INLL|FOREFF, + SHLL|SNAME|SOREG, TLL, + SHLL|SCON, TLL, + 0, RLEFT, + " addl AR,AL\n adcl UR,UL\n", }, + +/* Special treatment for long long XXX - fix commutative check */ +{ PLUS, INLL|FOREFF, + SHLL|SNAME|SOREG, TLL, + SHLL, TLL, + 0, RRIGHT, + " addl AL,AR\n adcl UL,UR\n", }, + +{ PLUS, INFL, + SHFL, TDOUBLE, + SNAME|SOREG, TDOUBLE, + 0, RLEFT, + " faddl AR\n", }, + +{ PLUS, INFL|FOREFF, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + 0, RLEFT, + " faddp\n", }, + +{ PLUS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TWORD|TPOINT, + SONE, TANY, + 0, RLEFT, + " incl AL\n", }, + +{ PLUS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TSHORT|TUSHORT, + SONE, TANY, + 0, RLEFT, + " incw AL\n", }, + +{ PLUS, INCH|FOREFF, + SHCH|SNAME|SOREG, TCHAR|TUCHAR, + SONE, TANY, + 0, RLEFT, + " incb AL\n", }, + +{ PLUS, INAREG, + SAREG, TWORD, + SAREG, TWORD, + NAREG|NASL|NASR, RESC1, + " leal (AL,AR),A1\n", }, + +{ MINUS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TWORD|TPOINT, + SONE, TANY, + 0, RLEFT, + " decl AL\n", }, + +{ MINUS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TSHORT|TUSHORT, + SONE, TANY, + 0, RLEFT, + " decw AL\n", }, + +{ MINUS, INCH|FOREFF, + SHCH|SNAME|SOREG, TCHAR|TUCHAR, + SONE, TANY, + 0, RLEFT, + " decb AL\n", }, + +/* address as register offset, negative */ +{ MINUS, INLL|FOREFF, + SHLL, TLL, + SHLL|SNAME|SOREG, TLL, + 0, RLEFT, + " subl AR,AL\n sbbl UR,UL\n", }, + +{ MINUS, INLL|FOREFF, + SHLL|SNAME|SOREG, TLL, + SHLL|SCON, TLL, + 0, RLEFT, + " subl AR,AL\n sbbl UR,UL\n", }, + +{ MINUS, INFL, + SHFL, TDOUBLE, + SNAME|SOREG, TDOUBLE, + 0, RLEFT, + " fsubl AR\n", }, + +{ MINUS, INFL|FOREFF, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + 0, RLEFT, + " fsubZAp\n", }, + +/* Simple r/m->reg ops */ +/* m/r |= r */ +{ OPSIMP, INAREG|FOREFF|FORCC, + SAREG|SNAME|SOREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + 0, RLEFT|RESCC, + " Ol AR,AL\n", }, + +/* r |= r/m */ +{ OPSIMP, INAREG|FOREFF|FORCC, + SAREG, TWORD|TPOINT, + SAREG|SNAME|SOREG, TWORD|TPOINT, + 0, RLEFT|RESCC, + " Ol AR,AL\n", }, + +/* m/r |= r */ +{ OPSIMP, INAREG|FOREFF|FORCC, + SHINT|SNAME|SOREG, TSHORT|TUSHORT, + SHINT, TSHORT|TUSHORT, + 0, RLEFT|RESCC, + " Ow AR,AL\n", }, + +/* r |= r/m */ +{ OPSIMP, INAREG|FOREFF|FORCC, + SHINT, TSHORT|TUSHORT, + SHINT|SNAME|SOREG, TSHORT|TUSHORT, + 0, RLEFT|RESCC, + " Ow AR,AL\n", }, + +/* m/r |= r */ +{ OPSIMP, INCH|FOREFF|FORCC, + SHCH, TCHAR|TUCHAR, + SHCH|SNAME|SOREG, TCHAR|TUCHAR, + 0, RLEFT|RESCC, + " Ob AR,AL\n", }, + +/* r |= r/m */ +{ OPSIMP, INCH|FOREFF|FORCC, + SHCH, TCHAR|TUCHAR, + SHCH|SNAME|SOREG, TCHAR|TUCHAR, + 0, RLEFT|RESCC, + " Ob AR,AL\n", }, + +/* m/r |= const */ +{ OPSIMP, INAREG|FOREFF|FORCC, + SAREG|SNAME|SOREG, TWORD|TPOINT, + SCON, TWORD|TPOINT, + 0, RLEFT|RESCC, + " Ol AR,AL\n", }, + +{ OPSIMP, INAREG|FOREFF|FORCC, + SHINT|SNAME|SOREG, TSHORT|TUSHORT, + SCON, TANY, + 0, RLEFT|RESCC, + " Ow AR,AL\n", }, + +{ OPSIMP, INCH|FOREFF|FORCC, + SHCH|SNAME|SOREG, TCHAR|TUCHAR, + SCON, TANY, + 0, RLEFT|RESCC, + " Ob AR,AL\n", }, + +/* r |= r/m */ +{ OPSIMP, INLL|FOREFF, + SHLL, TLL, + SHLL|SNAME|SOREG, TLL, + 0, RLEFT, + " Ol AR,AL\n Ol UR,UL\n", }, + +/* m/r |= r/const */ +{ OPSIMP, INLL|FOREFF, + SHLL|SNAME|SOREG, TLL, + SHLL|SCON, TLL, + 0, RLEFT, + " Ol AR,AL\n Ol UR,UL\n", }, + +/* Try use-reg instructions first */ +{ PLUS, INAREG, + SAREG, TWORD|TPOINT, + SCON, TANY, + NAREG|NASL, RESC1, + " leal CR(AL),A1\n", }, + +{ MINUS, INAREG, + SAREG, TWORD|TPOINT, + SPCON, TANY, + NAREG|NASL, RESC1, + " leal -CR(AL),A1\n", }, + + +/* + * The next rules handle all shift operators. + */ +/* (u)longlong left shift is emulated */ +{ LS, INCREG, + SCREG, TLL, + SHCH, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + "ZO", }, + +/* r/m <<= r */ +{ LS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TWORD, + SHCH, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " sall AR,AL\n", }, + +/* r/m <<= const */ +{ LS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TWORD, + SCON, TANY, + 0, RLEFT, + " sall AR,AL\n", }, + +/* r/m <<= r */ +{ LS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TSHORT|TUSHORT, + SHCH, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " shlw AR,AL\n", }, + +/* r/m <<= const */ +{ LS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TSHORT|TUSHORT, + SCON, TANY, + 0, RLEFT, + " shlw AR,AL\n", }, + +{ LS, INCH|FOREFF, + SHCH|SNAME|SOREG, TCHAR|TUCHAR, + SHCH, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " salb AR,AL\n", }, + +{ LS, INCH|FOREFF, + SHCH|SNAME|SOREG, TCHAR|TUCHAR, + SCON, TANY, + 0, RLEFT, + " salb AR,AL\n", }, + +/* (u)longlong right shift is emulated */ +{ RS, INCREG, + SCREG, TLL, + SHCH, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + "ZO", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TSWORD, + SHCH, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " sarl AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TSWORD, + SCON, TANY, + 0, RLEFT, + " sarl AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TUWORD, + SHCH, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " shrl AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TUWORD, + SCON, TANY, + 0, RLEFT, + " shrl AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TSHORT, + SHCH, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " sarw AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TSHORT, + SCON, TANY, + 0, RLEFT, + " sarw AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TUSHORT, + SHCH, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " shrw AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TUSHORT, + SCON, TANY, + 0, RLEFT, + " shrw AR,AL\n", }, + +{ RS, INCH|FOREFF, + SHCH|SNAME|SOREG, TCHAR, + SHCH, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " sarb AR,AL\n", }, + +{ RS, INCH|FOREFF, + SHCH|SNAME|SOREG, TCHAR, + SCON, TANY, + 0, RLEFT, + " sarb AR,AL\n", }, + +{ RS, INCH|FOREFF, + SHCH|SNAME|SOREG, TUCHAR, + SHCH, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " shrb AR,AL\n", }, + +{ RS, INCH|FOREFF, + SHCH|SNAME|SOREG, TUCHAR, + SCON, TANY, + 0, RLEFT, + " shrb AR,AL\n", }, + +/* + * The next rules takes care of assignments. "=". + */ +{ ASSIGN, FORCC|FOREFF|INLL, + SHLL, TLL, + SMIXOR, TANY, + 0, RDEST, + " xorl AL,AL\n xorl UL,UL\n", }, + +{ ASSIGN, FORCC|FOREFF|INLL, + SHLL, TLL, + SMILWXOR, TANY, + 0, RDEST, + " xorl AL,AL\n movl UR,UL\n", }, + +{ ASSIGN, FORCC|FOREFF|INLL, + SHLL, TLL, + SMIHWXOR, TANY, + 0, RDEST, + " movl AR,AL\n xorl UL,UL\n", }, + +{ ASSIGN, FOREFF|INLL, + SHLL, TLL, + SCON, TANY, + 0, RDEST, + " movl AR,AL\n movl UR,UL\n", }, + +{ ASSIGN, FOREFF, + SHLL|SNAME|SOREG, TLL, + SCON, TANY, + 0, 0, + " movl AR,AL\n movl UR,UL\n", }, + +{ ASSIGN, FORCC|FOREFF|INAREG, + SAREG, TWORD|TPOINT, + SMIXOR, TANY, + 0, RDEST, + " xorl AL,AL\n", }, + +{ ASSIGN, FOREFF, + SAREG|SNAME|SOREG, TWORD|TPOINT, + SCON, TANY, + 0, 0, + " movl AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TWORD|TPOINT, + SCON, TANY, + 0, RDEST, + " movl AR,AL\n", }, + +{ ASSIGN, FORCC|FOREFF|INAREG, + SAREG, TSHORT|TUSHORT, + SMIXOR, TANY, + 0, RDEST, + " xorw AL,AL\n", }, + +{ ASSIGN, FOREFF, + SAREG|SNAME|SOREG, TSHORT|TUSHORT, + SCON, TANY, + 0, 0, + " movw AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TSHORT|TUSHORT, + SCON, TANY, + 0, RDEST, + " movw AR,AL\n", }, + +{ ASSIGN, FOREFF, + SHCH|SNAME|SOREG, TCHAR|TUCHAR, + SCON, TANY, + 0, 0, + " movb AR,AL\n", }, + +{ ASSIGN, FOREFF|INCH, + SHCH, TCHAR|TUCHAR, + SCON, TANY, + 0, RDEST, + " movb AR,AL\n", }, + +{ ASSIGN, FOREFF|INLL, + SNAME|SOREG, TLL, + SHLL, TLL, + 0, RDEST, + " movl AR,AL\n movl UR,UL\n", }, + +{ ASSIGN, FOREFF|INLL, + SHLL, TLL, + SHLL, TLL, + 0, RDEST, + "ZH", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG|SNAME|SOREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + 0, RDEST, + " movl AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TWORD|TPOINT, + SAREG|SNAME|SOREG, TWORD|TPOINT, + 0, RDEST, + " movl AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG|SNAME|SOREG, TSHORT|TUSHORT, + SAREG, TSHORT|TUSHORT, + 0, RDEST, + " movw AR,AL\n", }, + +{ ASSIGN, FOREFF|INCH, + SHCH|SNAME|SOREG, TCHAR|TUCHAR, + SHCH, TCHAR|TUCHAR|TWORD, + 0, RDEST, + " movb AR,AL\n", }, + +{ ASSIGN, FOREFF|INBREG, + SFLD, TCHAR|TUCHAR, + SBREG|SCON, TCHAR|TUCHAR, + NAREG|NBREG, RDEST, + " movb AR,A2\n" + " movzbl A2,A1\n" + " andl $N,AL\n" + " sall $H,A1\n" + " andl $M,A1\n" + " orl A1,AL\n" + "F movb AR,AD\n" + "FZE", }, + +{ ASSIGN, FOREFF|INAREG, + SFLD, TSHORT|TUSHORT, + SAREG|SCON, TSHORT|TUSHORT, + NAREG, RDEST, + " movw AR,A1\n" + " movzwl A1,ZN\n" + " andl $N,AL\n" + " sall $H,ZN\n" + " andl $M,ZN\n" + " orl ZN,AL\n" + "F movw AR,AD\n" + "FZE", }, + +{ ASSIGN, FOREFF|INAREG, + SFLD, TWORD, + SAREG|SNAME|SOREG|SCON, TWORD, + NAREG, RDEST, + " movl AR,A1\n" + " andl $N,AL\n" + " sall $H,A1\n" + " andl $M,A1\n" + " orl A1,AL\n" + "ZB" + "F movl AR,AD\n" + "FZE", }, + + +{ ASSIGN, FOREFF|INCREG, + SFLD, TLL, + SCREG, TLL, + NCREG, RDEST, + "ZL", }, + + +{ ASSIGN, INDREG|FOREFF, + SHFL, TFLOAT|TDOUBLE|TLDOUBLE, + SHFL, TFLOAT|TDOUBLE|TLDOUBLE, + 0, RDEST, + "", }, /* This will always be in the correct register */ + +/* order of table entries is very important here! */ +{ ASSIGN, INFL, + SNAME|SOREG, TLDOUBLE, + SHFL, TFLOAT|TDOUBLE|TLDOUBLE, + 0, RDEST, + " fstpt AL\n fldt AL\n", }, /* XXX */ + +{ ASSIGN, FOREFF, + SNAME|SOREG, TLDOUBLE, + SHFL, TFLOAT|TDOUBLE|TLDOUBLE, + 0, 0, + " fstpt AL\n", }, + +{ ASSIGN, INFL, + SNAME|SOREG, TDOUBLE, + SHFL, TFLOAT|TDOUBLE|TLDOUBLE, + 0, RDEST, + " fstl AL\n", }, + +{ ASSIGN, FOREFF, + SNAME|SOREG, TDOUBLE, + SHFL, TFLOAT|TDOUBLE|TLDOUBLE, + 0, 0, + " fstpl AL\n", }, + +{ ASSIGN, INFL, + SNAME|SOREG, TFLOAT, + SHFL, TFLOAT|TDOUBLE|TLDOUBLE, + 0, RDEST, + " fsts AL\n", }, + +{ ASSIGN, FOREFF, + SNAME|SOREG, TFLOAT, + SHFL, TFLOAT|TDOUBLE|TLDOUBLE, + 0, 0, + " fstps AL\n", }, +/* end very important order */ + +{ ASSIGN, INFL|FOREFF, + SHFL, TLDOUBLE, + SHFL|SOREG|SNAME, TLDOUBLE, + 0, RDEST, + " fldt AR\n", }, + +{ ASSIGN, INFL|FOREFF, + SHFL, TDOUBLE, + SHFL|SOREG|SNAME, TDOUBLE, + 0, RDEST, + " fldl AR\n", }, + +{ ASSIGN, INFL|FOREFF, + SHFL, TFLOAT, + SHFL|SOREG|SNAME, TFLOAT, + 0, RDEST, + " flds AR\n", }, + +/* Do not generate memcpy if return from funcall */ +#if 0 +{ STASG, INAREG|FOREFF, + SOREG|SNAME|SAREG, TPTRTO|TSTRUCT, + SFUNCALL, TPTRTO|TSTRUCT, + 0, RRIGHT, + "", }, +#endif + +{ STASG, INAREG|FOREFF, + SOREG|SNAME, TANY, + SAREG, TPTRTO|TANY, + NSPECIAL, RDEST, + "ZQ", }, + +/* + * DIV/MOD/MUL + */ +/* long long div is emulated */ +{ DIV, INCREG, + SCREG|SNAME|SOREG|SCON, TLL, + SCREG|SNAME|SOREG|SCON, TLL, + NSPECIAL|NCREG|NCSL|NCSR, RESC1, + "ZO", }, + +{ DIV, INAREG, + SAREG, TSWORD, + SAREG|SNAME|SOREG, TWORD, + NSPECIAL, RDEST, + " cltd\n idivl AR\n", }, + +{ DIV, INAREG, + SAREG, TUWORD|TPOINT, + SAREG|SNAME|SOREG, TUWORD|TPOINT, + NSPECIAL, RDEST, + " xorl %edx,%edx\n divl AR\n", }, + +{ DIV, INAREG, + SAREG, TUSHORT, + SAREG|SNAME|SOREG, TUSHORT, + NSPECIAL, RDEST, + " xorl %edx,%edx\n divw AR\n", }, + +{ DIV, INCH, + SHCH, TUCHAR, + SHCH|SNAME|SOREG, TUCHAR, + NSPECIAL, RDEST, + " xorb %ah,%ah\n divb AR\n", }, + +{ DIV, INFL, + SHFL, TDOUBLE, + SNAME|SOREG, TDOUBLE, + 0, RLEFT, + " fdivl AR\n", }, + +{ DIV, INFL, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + 0, RLEFT, + " fdivZAp\n", }, + +/* (u)longlong mod is emulated */ +{ MOD, INCREG, + SCREG|SNAME|SOREG|SCON, TLL, + SCREG|SNAME|SOREG|SCON, TLL, + NSPECIAL|NCREG|NCSL|NCSR, RESC1, + "ZO", }, + +{ MOD, INAREG, + SAREG, TSWORD, + SAREG|SNAME|SOREG, TSWORD, + NAREG|NSPECIAL, RESC1, + " cltd\n idivl AR\n", }, + +{ MOD, INAREG, + SAREG, TWORD|TPOINT, + SAREG|SNAME|SOREG, TUWORD|TPOINT, + NAREG|NSPECIAL, RESC1, + " xorl %edx,%edx\n divl AR\n", }, + +{ MOD, INAREG, + SAREG, TUSHORT, + SAREG|SNAME|SOREG, TUSHORT, + NAREG|NSPECIAL, RESC1, + " xorl %edx,%edx\n divw AR\n", }, + +{ MOD, INCH, + SHCH, TUCHAR, + SHCH|SNAME|SOREG, TUCHAR, + NBREG|NSPECIAL, RESC1, + " xorb %ah,%ah\n divb AR\n", }, + +/* (u)longlong mul is emulated */ +{ MUL, INCREG, + SCREG, TLL, + SCREG, TLL, + NSPECIAL, RLEFT, + "ZO", }, + +{ MUL, INAREG, + SAREG, TWORD|TPOINT, + SAREG|SNAME|SOREG|SCON, TWORD|TPOINT, + 0, RLEFT, + " imull AR,AL\n", }, + +{ MUL, INAREG, + SAREG, TSHORT|TUSHORT, + SAREG|SNAME|SOREG, TSHORT|TUSHORT, + 0, RLEFT, + " imulw AR,AL\n", }, + +{ MUL, INCH, + SHCH, TCHAR|TUCHAR, + SHCH|SNAME|SOREG, TCHAR|TUCHAR, + NSPECIAL, RDEST, + " imulb AR\n", }, + +{ MUL, INFL, + SHFL, TDOUBLE, + SNAME|SOREG, TDOUBLE, + 0, RLEFT, + " fmull AR\n", }, + +{ MUL, INFL, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + 0, RLEFT, + " fmulp\n", }, + +/* + * Indirection operators. + */ +{ UMUL, INLL, + SANY, TANY, + SOREG, TLL, + NCREG, RESC1, + " movl UL,U1\n movl AL,A1\n", }, + +{ UMUL, INAREG, + SANY, TPOINT|TWORD, + SOREG, TPOINT|TWORD, + NAREG|NASL, RESC1, + " movl AL,A1\n", }, + +{ UMUL, INCH, + SANY, TANY, + SOREG, TCHAR|TUCHAR, + NBREG|NBSL, RESC1, + " movb AL,A1\n", }, + +{ UMUL, INAREG, + SANY, TANY, + SOREG, TSHORT|TUSHORT, + NAREG|NASL, RESC1, + " movw AL,A1\n", }, + +{ UMUL, INFL, + SANY, TANY, + SOREG, TLDOUBLE, + NDREG|NDSL, RESC1, + " fldt AL\n", }, + +{ UMUL, INFL, + SANY, TANY, + SOREG, TDOUBLE, + NDREG|NDSL, RESC1, + " fldl AL\n", }, + +{ UMUL, INFL, + SANY, TANY, + SOREG, TFLOAT, + NDREG|NDSL, RESC1, + " flds AL\n", }, + +/* + * Logical/branching operators + */ + +/* Comparisions, take care of everything */ +{ OPLOG, FORCC, + SHLL|SOREG|SNAME, TLL, + SHLL, TLL, + 0, 0, + "ZD", }, + +{ OPLOG, FORCC, + SAREG|SOREG|SNAME, TWORD|TPOINT, + SCON|SAREG, TWORD|TPOINT, + 0, RESCC, + " cmpl AR,AL\n", }, + +{ OPLOG, FORCC, + SCON|SAREG, TWORD|TPOINT, + SAREG|SOREG|SNAME, TWORD|TPOINT, + 0, RESCC, + " cmpl AR,AL\n", }, + +{ OPLOG, FORCC, + SAREG|SOREG|SNAME, TSHORT|TUSHORT, + SCON|SAREG, TANY, + 0, RESCC, + " cmpw AR,AL\n", }, + +{ OPLOG, FORCC, + SBREG|SOREG|SNAME, TCHAR|TUCHAR, + SCON|SBREG, TANY, + 0, RESCC, + " cmpb AR,AL\n", }, + +{ OPLOG, FORCC, + SDREG, TLDOUBLE|TDOUBLE|TFLOAT, + SDREG, TLDOUBLE|TDOUBLE|TFLOAT, + 0, RNOP, + "ZG", }, + +{ OPLOG, FORCC, + SANY, TANY, + SANY, TANY, + REWRITE, 0, + "diediedie!", }, + +/* AND/OR/ER/NOT */ +{ AND, INAREG|FOREFF, + SAREG|SOREG|SNAME, TWORD, + SCON|SAREG, TWORD, + 0, RLEFT, + " andl AR,AL\n", }, + +{ AND, INCREG|FOREFF, + SCREG, TLL, + SCREG|SOREG|SNAME, TLL, + 0, RLEFT, + " andl AR,AL\n andl UR,UL\n", }, + +{ AND, INAREG|FOREFF, + SAREG, TWORD, + SAREG|SOREG|SNAME, TWORD, + 0, RLEFT, + " andl AR,AL\n", }, + +{ AND, INAREG|FOREFF, + SAREG|SOREG|SNAME, TSHORT|TUSHORT, + SCON|SAREG, TSHORT|TUSHORT, + 0, RLEFT, + " andw AR,AL\n", }, + +{ AND, INAREG|FOREFF, + SAREG, TSHORT|TUSHORT, + SAREG|SOREG|SNAME, TSHORT|TUSHORT, + 0, RLEFT, + " andw AR,AL\n", }, + +{ AND, INBREG|FOREFF, + SBREG|SOREG|SNAME, TCHAR|TUCHAR, + SCON|SBREG, TCHAR|TUCHAR, + 0, RLEFT, + " andb AR,AL\n", }, + +{ AND, INBREG|FOREFF, + SBREG, TCHAR|TUCHAR, + SBREG|SOREG|SNAME, TCHAR|TUCHAR, + 0, RLEFT, + " andb AR,AL\n", }, +/* AND/OR/ER/NOT */ + +/* + * Jumps. + */ +{ GOTO, FOREFF, + SCON, TANY, + SANY, TANY, + 0, RNOP, + " jmp LL\n", }, + +#if defined(GCC_COMPAT) || defined(LANG_F77) +{ GOTO, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, RNOP, + " jmp *AL\n", }, +#endif + +/* + * Convert LTYPE to reg. + */ +{ OPLTYPE, FORCC|INLL, + SCREG, TLL, + SMIXOR, TANY, + NCREG, RESC1, + " xorl U1,U1\n xorl A1,A1\n", }, + +{ OPLTYPE, FORCC|INLL, + SCREG, TLL, + SMILWXOR, TANY, + NCREG, RESC1, + " movl UL,U1\n xorl A1,A1\n", }, + +{ OPLTYPE, FORCC|INLL, + SCREG, TLL, + SMIHWXOR, TANY, + NCREG, RESC1, + " xorl U1,U1\n movl AL,A1\n", }, + +{ OPLTYPE, INLL, + SANY, TANY, + SCREG, TLL, + NCREG, RESC1, + "ZK", }, + +{ OPLTYPE, INLL, + SANY, TANY, + SCON|SOREG|SNAME, TLL, + NCREG, RESC1, + " movl UL,U1\n movl AL,A1\n", }, + +{ OPLTYPE, FORCC|INAREG, + SAREG, TWORD|TPOINT, + SMIXOR, TANY, + NAREG|NASL, RESC1, + " xorl A1,A1\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SAREG|SCON|SOREG|SNAME, TWORD|TPOINT, + NAREG|NASL, RESC1, + " movl AL,A1\n", }, + +{ OPLTYPE, INBREG, + SANY, TANY, + SBREG|SOREG|SNAME|SCON, TCHAR|TUCHAR, + NBREG, RESC1, + " movb AL,A1\n", }, + +{ OPLTYPE, FORCC|INAREG, + SAREG, TSHORT|TUSHORT, + SMIXOR, TANY, + NAREG, RESC1, + " xorw A1,A1\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SAREG|SOREG|SNAME|SCON, TSHORT|TUSHORT, + NAREG, RESC1, + " movw AL,A1\n", }, + +{ OPLTYPE, INDREG, + SANY, TLDOUBLE, + SOREG|SNAME, TLDOUBLE, + NDREG, RESC1, + " fldt AL\n", }, + +{ OPLTYPE, INDREG, + SANY, TDOUBLE, + SOREG|SNAME, TDOUBLE, + NDREG, RESC1, + " fldl AL\n", }, + +{ OPLTYPE, INDREG, + SANY, TFLOAT, + SOREG|SNAME, TFLOAT, + NDREG, RESC1, + " flds AL\n", }, + +/* Only used in ?: constructs. The stack already contains correct value */ +{ OPLTYPE, INDREG, + SANY, TFLOAT|TDOUBLE|TLDOUBLE, + SDREG, TFLOAT|TDOUBLE|TLDOUBLE, + NDREG, RESC1, + "", }, + +/* + * Negate a word. + */ + +{ UMINUS, INCREG|FOREFF, + SCREG, TLL, + SCREG, TLL, + 0, RLEFT, + " negl AL\n adcl $0,UL\n negl UL\n", }, + +{ UMINUS, INAREG|FOREFF, + SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + 0, RLEFT, + " negl AL\n", }, + +{ UMINUS, INAREG|FOREFF, + SAREG, TSHORT|TUSHORT, + SAREG, TSHORT|TUSHORT, + 0, RLEFT, + " negw AL\n", }, + +{ UMINUS, INBREG|FOREFF, + SBREG, TCHAR|TUCHAR, + SBREG, TCHAR|TUCHAR, + 0, RLEFT, + " negb AL\n", }, + +{ UMINUS, INFL|FOREFF, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + 0, RLEFT, + " fchs\n", }, + +{ COMPL, INCREG, + SCREG, TLL, + SANY, TANY, + 0, RLEFT, + " notl AL\n notl UL\n", }, + +{ COMPL, INAREG, + SAREG, TWORD, + SANY, TANY, + 0, RLEFT, + " notl AL\n", }, + +{ COMPL, INAREG, + SAREG, TSHORT|TUSHORT, + SANY, TANY, + 0, RLEFT, + " notw AL\n", }, + +{ COMPL, INBREG, + SBREG, TCHAR|TUCHAR, + SANY, TANY, + 0, RLEFT, + " notb AL\n", }, + +/* + * Arguments to functions. + */ +{ FUNARG, FOREFF, + SCON|SCREG|SNAME|SOREG, TLL, + SANY, TLL, + 0, RNULL, + " pushl UL\n pushl AL\n", }, + +{ FUNARG, FOREFF, + SCON|SAREG|SNAME|SOREG, TWORD|TPOINT, + SANY, TWORD|TPOINT, + 0, RNULL, + " pushl AL\n", }, + +{ FUNARG, FOREFF, + SCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SANY, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + 0, RNULL, + " pushl AL\n", }, + +{ FUNARG, FOREFF, + SAREG|SNAME|SOREG, TSHORT, + SANY, TSHORT, + NAREG, 0, + " movswl AL,ZN\n pushl ZN\n", }, + +{ FUNARG, FOREFF, + SAREG|SNAME|SOREG, TUSHORT, + SANY, TUSHORT, + NAREG, 0, + " movzwl AL,ZN\n pushl ZN\n", }, + +{ FUNARG, FOREFF, + SHCH|SNAME|SOREG, TCHAR, + SANY, TCHAR, + NAREG, 0, + " movsbl AL,A1\n pushl A1\n", }, + +{ FUNARG, FOREFF, + SHCH|SNAME|SOREG, TUCHAR, + SANY, TUCHAR, + NAREG, 0, + " movzbl AL,A1\n pushl A1\n", }, + +{ FUNARG, FOREFF, + SNAME|SOREG, TDOUBLE, + SANY, TDOUBLE, + 0, 0, + " pushl UL\n pushl AL\n", }, + +{ FUNARG, FOREFF, + SDREG, TDOUBLE, + SANY, TDOUBLE, + 0, 0, + " subl $8,%esp\n fstpl (%esp)\n", }, + +{ FUNARG, FOREFF, + SNAME|SOREG, TFLOAT, + SANY, TFLOAT, + 0, 0, + " pushl AL\n", }, + +{ FUNARG, FOREFF, + SDREG, TFLOAT, + SANY, TFLOAT, + 0, 0, + " subl $4,%esp\n fstps (%esp)\n", }, + +{ FUNARG, FOREFF, + SDREG, TLDOUBLE, + SANY, TLDOUBLE, + 0, 0, + " subl $12,%esp\n fstpt (%esp)\n", }, + +{ STARG, FOREFF, + SAREG|SOREG|SNAME|SCON, TANY, + SANY, TSTRUCT, + NSPECIAL|NAREG, 0, + "ZF", }, + +# define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,"" + +{ UMUL, DF( UMUL ), }, + +{ ASSIGN, DF(ASSIGN), }, + +{ STASG, DF(STASG), }, + +{ FLD, DF(FLD), }, + +{ OPLEAF, DF(NAME), }, + +/* { INIT, DF(INIT), }, */ + +{ OPUNARY, DF(UMINUS), }, + +{ OPANY, DF(BITYPE), }, + +{ FREE, FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" }, +}; + +int tablesize = sizeof(table)/sizeof(table[0]); diff --git a/compilers/pcc/pcc-1.0.0/arch/m16c/CVS/Entries b/compilers/pcc/pcc-1.0.0/arch/m16c/CVS/Entries new file mode 100644 index 00000000..cc9d9d00 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/m16c/CVS/Entries @@ -0,0 +1,8 @@ +/TODO/1.3/Mon Feb 6 09:33:09 2006//Tr-1-0-0-RELEASE +/code.c/1.20/Tue Jul 29 13:25:58 2008//Tr-1-0-0-RELEASE +/local.c/1.15/Sun Dec 14 21:16:58 2008//Tr-1-0-0-RELEASE +/local2.c/1.40/Sat Nov 22 16:12:24 2008//Tr-1-0-0-RELEASE +/macdefs.h/1.23/Fri Nov 16 22:23:04 2007//Tr-1-0-0-RELEASE +/order.c/1.20/Sat Sep 27 07:35:23 2008//Tr-1-0-0-RELEASE +/table.c/1.34/Sun Feb 10 19:25:43 2008//Tr-1-0-0-RELEASE +D diff --git a/compilers/pcc/pcc-1.0.0/arch/m16c/CVS/Repository b/compilers/pcc/pcc-1.0.0/arch/m16c/CVS/Repository new file mode 100644 index 00000000..806659b7 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/m16c/CVS/Repository @@ -0,0 +1 @@ +pcc/arch/m16c diff --git a/compilers/pcc/pcc-1.0.0/arch/m16c/CVS/Root b/compilers/pcc/pcc-1.0.0/arch/m16c/CVS/Root new file mode 100644 index 00000000..71e2ccb9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/m16c/CVS/Root @@ -0,0 +1 @@ +/cvsroot diff --git a/compilers/pcc/pcc-1.0.0/arch/m16c/CVS/Tag b/compilers/pcc/pcc-1.0.0/arch/m16c/CVS/Tag new file mode 100644 index 00000000..060fac05 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/m16c/CVS/Tag @@ -0,0 +1 @@ +Nr-1-0-0-RELEASE diff --git a/compilers/pcc/pcc-1.0.0/arch/m16c/TODO b/compilers/pcc/pcc-1.0.0/arch/m16c/TODO new file mode 100644 index 00000000..5ef0ba4b --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/m16c/TODO @@ -0,0 +1 @@ +* Mul/Div does not work. \ No newline at end of file diff --git a/compilers/pcc/pcc-1.0.0/arch/m16c/code.c b/compilers/pcc/pcc-1.0.0/arch/m16c/code.c new file mode 100644 index 00000000..8af16b9a --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/m16c/code.c @@ -0,0 +1,350 @@ +/* $Id: code.c,v 1.20 2008/07/29 13:25:58 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass1.h" + +/* + * cause the alignment to become a multiple of n + */ +void +defalign(int n) +{ +#if 0 + char *s; + + n /= SZCHAR; + if (lastloc == PROG || n == 1) + return; + s = (isinlining ? permalloc(40) : tmpalloc(40)); + sprintf(s, ".align %d", n); + send_passt(IP_ASM, s); +#endif +} + +/* + * define the current location as the name p->soname + */ +void +defnam(struct symtab *p) +{ + char *c = p->soname; + + if (p->sclass == EXTDEF) + printf(" PUBLIC %s\n", c); + printf("%s:\n", c); +} + + +/* + * code for the end of a function + * deals with struct return here + */ +void +efcode() +{ + NODE *p, *q; + int sz; + + if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) + return; + /* address of return struct is in eax */ + /* create a call to memcpy() */ + /* will get the result in eax */ + p = block(REG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR)); + p->n_rval = R0; + q = block(OREG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR)); + q->n_rval = FB; + q->n_lval = 8; /* return buffer offset */ + p = block(CM, q, p, INT, 0, MKSUE(INT)); + sz = (tsize(STRTY, cftnsp->sdf, cftnsp->ssue)+SZCHAR-1)/SZCHAR; + p = block(CM, p, bcon(sz), INT, 0, MKSUE(INT)); + p->n_right->n_name = ""; + p = block(CALL, bcon(0), p, CHAR+PTR, 0, MKSUE(CHAR+PTR)); + p->n_left->n_name = "memcpy"; + send_passt(IP_NODE, p); +} + +/* + * helper for bfcode() to put register arguments on stack. + */ +static void +argmove(struct symtab *s, int regno) +{ + NODE *p, *r; + + s->sclass = AUTO; + s->soffset = NOOFFSET; + oalloc(s, &autooff); + p = nametree(s); + r = bcon(0); + r->n_op = REG; + r->n_rval = regno; + r->n_type = p->n_type; + r->n_sue = p->n_sue; + r->n_df = p->n_df; + ecode(buildtree(ASSIGN, p, r)); +} + +/* + * code for the beginning of a function; a is an array of + * indices in symtab for the arguments; n is the number + * On m16k, space is allocated on stack for register arguments, + * arguments are moved to the stack and symtab is updated accordingly. + */ +void +bfcode(struct symtab **a, int n) +{ + struct symtab *s; + int i, r0l, r0h, a0, r2, sz, hasch, stk; + int argoff = ARGINIT; + + if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) { + /* Function returns struct, adjust arg offset */ + for (i = 0; i < n; i++) + a[i]->soffset += SZPOINT(INT); + } + /* first check if there are 1-byte parameters */ + for (hasch = i = 0; i < n && i < 6; i++) + if (DEUNSIGN(a[i]->stype) == CHAR) + hasch = 1; + + stk = r0l = r0h = a0 = r2 = 0; + for (i = 0; i < n; i++) { + s = a[i]; + sz = tsize(s->stype, s->sdf, s->ssue); + if (ISPTR(s->stype) && ISFTN(DECREF(s->stype))) + sz = SZLONG; /* function pointers are always 32 */ + if (stk == 0) + switch (sz) { + case SZCHAR: + if (r0l) { + if (r0h) + break; + argmove(s, 1); + r0h = 1; + } else { + argmove(s, 0); + r0l = 1; + } + continue; + + case SZINT: + if (s->stype > BTMASK) { + /* is a pointer */ + if (a0) { + if (r0l || hasch) { + if (r2) + break; + argmove(s, R2); + r2 = 1; + } else { + argmove(s, R0); + r0l = r0h = 1; + } + } else { + argmove(s, A0); + a0 = 1; + } + } else if (r0l || hasch) { + if (r2) { + if (a0) + break; + argmove(s, A0); + a0 = 1; + } else { + argmove(s, R2); + r2 = 1; + } + } else { + argmove(s, R0); + r0l = r0h = 1; + } + continue; + case SZLONG: + if (r0l||r0h||r2) + break; + argmove(s, R0); + r0l = r0h = r2 = 1; + continue; + + default: + break; + } + stk = 1; + s->soffset = argoff; + argoff += sz; + } +} + +/* + * Add a symbol to an internal list printed out at the end. + */ +void addsym(struct symtab *); +static struct symlst { + struct symlst *next; + struct symtab *sp; +} *sympole; + +void +addsym(struct symtab *q) +{ + struct symlst *w = sympole; + + if (q == NULL) + return; + + while (w) { + if (q == w->sp) + return; /* exists */ + w = w->next; + } + w = permalloc(sizeof(struct symlst)); + w->sp = q; + w->next = sympole; + sympole = w; +} + +/* + * by now, the automatics and register variables are allocated + */ +void +bccode() +{ +} + +struct caps { + char *cap, *stat; +} caps[] = { + { "__64bit_doubles", "Disabled" }, + { "__calling_convention", "Normal" }, + { "__constant_data", "near" }, + { "__data_alignment", "2" }, + { "__data_model", "near" }, + { "__processor", "M16C" }, + { "__rt_version", "1" }, + { "__variable_data", "near" }, + { NULL, NULL }, +}; +/* + * Called before parsing begins. + */ +void +bjobcode() +{ + struct caps *c; + + printf(" NAME gurka.c\n"); /* Don't have the name */ + for (c = caps; c->cap; c++) + printf(" RTMODEL \"%s\", \"%s\"\n", c->cap, c->stat); + //printf(" RSEG CODE:CODE:REORDER:NOROOT(0)\n"); +} + +/* called just before final exit */ +/* flag is 1 if errors, 0 if none */ +void +ejobcode(int flag ) +{ + struct symlst *w = sympole; + + for (w = sympole; w; w = w->next) { + if (w->sp->sclass != EXTERN) + continue; + printf(" EXTERN %s\n", w->sp->soname); + } + + printf(" END\n"); +} + +/* + * Print character t at position i in one string, until t == -1. + * Locctr & label is already defined. + */ +void +bycode(int t, int i) +{ + static int lastoctal = 0; + + /* put byte i+1 in a string */ + + if (t < 0) { + if (i != 0) + puts("\""); + } else { + if (i == 0) + printf("\t.ascii \""); + if (t == '\\' || t == '"') { + lastoctal = 0; + putchar('\\'); + putchar(t); + } else if (t < 040 || t >= 0177) { + lastoctal++; + printf("\\%o",t); + } else if (lastoctal && '0' <= t && t <= '9') { + lastoctal = 0; + printf("\"\n\t.ascii \"%c", t); + } else { + lastoctal = 0; + putchar(t); + } + } +} + +/* + * return the alignment of field of type t + */ +int +fldal(unsigned int t) +{ + uerror("illegal field type"); + return(ALINT); +} + +/* fix up type of field p */ +void +fldty(struct symtab *p) +{ +} + +/* + * XXX - fix genswitch. + */ +int +mygenswitch(int num, TWORD type, struct swents **p, int n) +{ + return 0; +} +/* + * Called with a function call with arguments as argument. + * This is done early in buildtree() and only done once. + */ +NODE * +funcode(NODE *p) +{ + return p; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/m16c/local.c b/compilers/pcc/pcc-1.0.0/arch/m16c/local.c new file mode 100644 index 00000000..f9d15e03 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/m16c/local.c @@ -0,0 +1,519 @@ +/* $Id: local.c,v 1.15 2008/12/14 21:16:58 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass1.h" + +/* this file contains code which is dependent on the target machine */ + +NODE * +clocal(NODE *p) +{ + /* this is called to do local transformations on + an expression tree preparitory to its being + written out in intermediate code. + */ + + /* the major essential job is rewriting the + automatic variables and arguments in terms of + REG and OREG nodes */ + /* conversion ops which are not necessary are also clobbered here */ + /* in addition, any special features (such as rewriting + exclusive or) are easily handled here as well */ + + struct symtab *q; + NODE *l, *r; + int o; + TWORD ml; + + switch( o = p->n_op ){ + + case NAME: + if ((q = p->n_sp) == NULL) + return p; /* Nothing to care about */ + + switch (q->sclass) { + + case PARAM: + case AUTO: + /* fake up a structure reference */ + r = block(REG, NIL, NIL, PTR+STRTY, 0, 0); + r->n_lval = 0; + r->n_rval = FPREG; + p = stref(block(STREF, r, p, 0, 0, 0)); + break; + + case STATIC: + if (q->slevel == 0) + break; + p->n_lval = 0; + p->n_sp = q; + break; + + case REGISTER: + p->n_op = REG; + p->n_lval = 0; + p->n_rval = q->soffset; + break; + + } + break; + + case PMCONV: + case PVCONV: + if( p->n_right->n_op != ICON ) cerror( "bad conversion", 0); + nfree(p); + return(buildtree(o==PMCONV?MUL:DIV, p->n_left, p->n_right)); + + case PCONV: + ml = p->n_left->n_type; + l = p->n_left; + if ((ml == CHAR || ml == UCHAR) && l->n_op != ICON) + break; + l->n_type = p->n_type; + l->n_qual = p->n_qual; + l->n_df = p->n_df; + l->n_sue = p->n_sue; + nfree(p); + p = l; + break; + + case SCONV: + l = p->n_left; + if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT) { + nfree(p); + return l; + } + if (l->n_op == ICON) { + CONSZ val = l->n_lval; + switch (p->n_type) { + case CHAR: + l->n_lval = (char)val; + break; + case UCHAR: + l->n_lval = val & 0377; + break; + case SHORT: + case INT: + l->n_lval = (short)val; + break; + case USHORT: + case UNSIGNED: + l->n_lval = val & 0177777; + break; + case ULONG: + case ULONGLONG: + l->n_lval = val & 0xffffffff; + break; + case LONG: + case LONGLONG: + l->n_lval = (int)val; + break; + case VOID: + break; + case LDOUBLE: + case DOUBLE: + case FLOAT: + l->n_op = FCON; + l->n_dcon = val; + break; + default: + cerror("unknown type %d", p->n_type); + } + l->n_type = p->n_type; + nfree(p); + return l; + } + break; + + + } + + return(p); +} + +/*ARGSUSED*/ +int +andable(NODE *p) +{ + return(1); /* all names can have & taken on them */ +} + +/* + * at the end of the arguments of a ftn, set the automatic offset + */ +void +cendarg() +{ + autooff = AUTOINIT; +} + +/* + * is an automatic variable of type t OK for a register variable + */ +int +cisreg(TWORD t) +{ + if (t == INT || t == UNSIGNED || t == CHAR || t == UCHAR || + ISPTR(t)) + return(1); + return 0; /* XXX - fix reg assignment in pftn.c */ +} + +/* + * return a node, for structure references, which is suitable for + * being added to a pointer of type t, in order to be off bits offset + * into a structure + * t, d, and s are the type, dimension offset, and sizeoffset + * For pdp10, return the type-specific index number which calculation + * is based on its size. For example, short a[3] would return 3. + * Be careful about only handling first-level pointers, the following + * indirections must be fullword. + */ +NODE * +offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue) +{ + register NODE *p; + + if (xdebug) + printf("offcon: OFFSZ %lld type %x dim %p siz %d\n", + off, t, d, sue->suesize); + + p = bcon(0); + p->n_lval = off/SZCHAR; /* Default */ + return(p); +} + +/* + * Allocate off bits on the stack. p is a tree that when evaluated + * is the multiply count for off, t is a NAME node where to write + * the allocated address. + */ +void +spalloc(NODE *t, NODE *p, OFFSZ off) +{ + NODE *sp; + + if ((off % SZINT) == 0) + p = buildtree(MUL, p, bcon(off/SZINT)); + else if ((off % SZSHORT) == 0) { + p = buildtree(MUL, p, bcon(off/SZSHORT)); + p = buildtree(PLUS, p, bcon(1)); + p = buildtree(RS, p, bcon(1)); + } else if ((off % SZCHAR) == 0) { + p = buildtree(MUL, p, bcon(off/SZCHAR)); + p = buildtree(PLUS, p, bcon(3)); + p = buildtree(RS, p, bcon(2)); + } else + cerror("roundsp"); + + /* save the address of sp */ + sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_sue); + sp->n_lval = 0; + sp->n_rval = STKREG; + t->n_type = sp->n_type; + ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */ + + /* add the size to sp */ + sp = block(REG, NIL, NIL, p->n_type, 0, 0); + sp->n_lval = 0; + sp->n_rval = STKREG; + ecomp(buildtree(PLUSEQ, sp, p)); +} + +/* + * print out a constant node + * mat be associated with a label + */ +void +ninval(NODE *p) +{ + struct symtab *q; + TWORD t; + + p = p->n_left; + t = p->n_type; + if (t > BTMASK) + t = INT; /* pointer */ + + switch (t) { + case LONGLONG: + case ULONGLONG: + inval(p->n_lval & 0xffffffff); + inval(p->n_lval >> 32); + break; + case LONG: + case ULONG: + case INT: + case UNSIGNED: + printf("\t.long 0x%x", (int)p->n_lval); + if ((q = p->n_sp) != NULL) { + if ((q->sclass == STATIC && q->slevel > 0)) { + printf("+" LABFMT, q->soffset); + } else + printf("+%s", exname(q->soname)); + } + printf("\n"); + break; + default: + fwalk(p, eprint, 0); + cerror("ninval"); + } +} + +/* + * print out an integer. + */ +void +inval(CONSZ word) +{ + word &= 0xffffffff; + printf(" .long 0x%llx\n", word); +} + +/* output code to initialize a floating point value */ +/* the proper alignment has been obtained */ +void +finval(NODE *p) +{ + switch (p->n_type) { + case LDOUBLE: + printf("\t.tfloat\t0t%.20Le\n", p->n_dcon); + break; + case DOUBLE: + printf("\t.dfloat\t0d%.20e\n", (double)p->n_dcon); + break; + case FLOAT: + printf("\t.ffloat\t0f%.20e\n", (float)p->n_dcon); + break; + } +} + +/* make a name look like an external name in the local machine */ +char * +exname(char *p) +{ + if (p == NULL) + return ""; + return p; +} + +/* + * map types which are not defined on the local machine + */ +TWORD +ctype(TWORD type) +{ + switch (BTYPE(type)) { + case SHORT: + MODTYPE(type,INT); + break; + + case USHORT: + MODTYPE(type,UNSIGNED); + break; + + case LONGLONG: + MODTYPE(type,LONG); + break; + + case ULONGLONG: + MODTYPE(type,ULONG); + break; + + case LDOUBLE: + MODTYPE(type,DOUBLE); + break; + } + return (type); +} + +/* curid is a variable which is defined but + * is not initialized (and not a function ); + * This routine returns the storage class for an uninitialized declaration + */ +int +noinit() +{ + return(EXTERN); +} + +/* + * Extern variable not necessary common. + */ +void +extdec(struct symtab *q) +{ + extern void addsym(struct symtab *); + addsym(q); +} + +/* + * Call to a function + */ +void +calldec(NODE *p, NODE *r) +{ + struct symtab *q = p->n_sp; + extern void addsym(struct symtab *); + addsym(q); +} + +/* make a common declaration for id, if reasonable */ +void +commdec(struct symtab *q) +{ + int off; + char *c = q->soname; + + off = tsize(q->stype, q->sdf, q->ssue); + off = (off+(SZCHAR-1))/SZCHAR; + + printf(" PUBLIC %s\n", c); + /* XXX - NOROOT??? */ + printf(" RSEG DATA16_Z:NEARDATA:SORT:NOROOT(1)\n"); + printf("%s:\n", c); + printf(" DS8 %d\n", off); + printf(" REQUIRE __data16_zero\n"); +} + +/* make a local common declaration for id, if reasonable */ +void +lcommdec(struct symtab *q) +{ + int off; + + off = tsize(q->stype, q->sdf, q->ssue); + off = (off+(SZCHAR-1))/SZCHAR; + if (q->slevel == 0) + printf(" .lcomm %s,0%o\n", exname(q->soname), off); + else + printf(" .lcomm " LABFMT ",0%o\n", q->soffset, off); +} + +/* + * print a (non-prog) label. + */ +void +deflab1(int label) +{ + printf(LABFMT ":\n", label); +} + +void +setloc1(int locc) +{ + if (locc == lastloc) + return; + lastloc = locc; +} + +/* + * special handling before tree is written out. + */ +void +myp2tree(NODE *p) +{ + struct symtab *sp; + union dimfun *df; + union arglist *al; + NODE *q; + int i; + + switch (p->n_op) { + case MOD: + case DIV: + if (p->n_type == LONG || p->n_type == ULONG) { + /* Swap arguments for hardops() later */ + q = p->n_left; + p->n_left = p->n_right; + p->n_right = q; + } + break; + + case CALL: + case STCALL: + /* + * inform pass2 about varargs. + * store first variadic argument number in n_stalign + * in the CM node. + */ + if (p->n_right->n_op != CM) + break; /* nothing to care about */ + df = p->n_left->n_df; + if (df && (al = df->dfun)) { + for (i = 0; i < 6; i++, al++) { + if (al->type == TELLIPSIS || al->type == TNULL) + break; + } + p->n_right->n_stalign = al->type == TELLIPSIS ? i : 0; + } else + p->n_right->n_stalign = 0; + break; + + case FCON: + /* Write float constants to memory */ + sp = inlalloc(sizeof(struct symtab)); + sp->sclass = STATIC; + sp->ssue = MKSUE(p->n_type); + sp->slevel = 1; /* fake numeric label */ + sp->soffset = getlab(); + sp->sflags = 0; + sp->stype = p->n_type; + sp->squal = (CON >> TSHIFT); + + defloc(sp); + ninval(0, sp->ssue->suesize, p); + + p->n_op = NAME; + p->n_lval = 0; + p->n_sp = sp; + break; + } + +} +/* + * Give target the opportunity of handling pragmas. + */ +int +mypragma(char **ary) +{ + return 0; } + +/* + * Called when a identifier has been declared, to give target last word. + */ +void +fixdef(struct symtab *sp) +{ +} + +void +pass1_lastchance(struct interpass *ip) +{ +} diff --git a/compilers/pcc/pcc-1.0.0/arch/m16c/local2.c b/compilers/pcc/pcc-1.0.0/arch/m16c/local2.c new file mode 100644 index 00000000..a47a7720 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/m16c/local2.c @@ -0,0 +1,664 @@ +/* $Id: local2.c,v 1.40 2008/11/22 16:12:24 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass2.h" +# include + +void acon(NODE *p); +int argsize(NODE *p); +void genargs(NODE *p); + +static int ftlab1, ftlab2; + +void +deflab(int label) +{ + printf(LABFMT ":\n", label); +} + +static TWORD ftype; +static int addto; + +void +prologue(struct interpass_prolog *ipp) +{ + ftype = ipp->ipp_type; + +#if 0 + if (ipp->ipp_regs > 0 && ipp->ipp_regs != MINRVAR) + comperr("fix prologue register savings", ipp->ipp_regs); +#endif + + printf(" RSEG CODE:CODE:REORDER:NOROOT(0)\n"); + if (ipp->ipp_vis) + printf(" PUBLIC %s\n", ipp->ipp_name); + printf("%s:\n", ipp->ipp_name); + +#if 0 + if (xsaveip) { + /* Optimizer running, save space on stack */ + addto = (p2maxautooff - AUTOINIT)/SZCHAR; + printf(" enter #%d\n", addto); + } else { +#endif + + /* non-optimized code, jump to epilogue for code generation */ + ftlab1 = getlab2(); + ftlab2 = getlab2(); + printf(" jmp.w " LABFMT "\n", ftlab1); + deflab(ftlab2); +} + +/* + * End of block. + */ +void +eoftn(struct interpass_prolog *ipp) +{ +#if 0 + if (ipp->ipp_regs != MINRVAR) + comperr("fix eoftn register savings %x", ipp->ipp_regs); +#endif + + // if (xsaveip == 0) + addto = (p2maxautooff - AUTOINIT)/SZCHAR; + + /* return from function code */ + //deflab(ipp->ipp_ip.ip_lbl); //XXX - is this necessary? + + /* If retval is a pointer and not a function pointer, put in A0 */ + if (ISPTR(DECREF(ipp->ipp_type)) && + !ISFTN(DECREF(DECREF(ipp->ipp_type)))) + printf(" mov.w r0,a0\n"); + + /* struct return needs special treatment */ + if (ftype == STRTY || ftype == UNIONTY) { + comperr("fix struct return in eoftn"); + } else + printf(" exitd\n"); + + /* Prolog code */ + // if (xsaveip == 0) { + deflab(ftlab1); + printf(" enter #%d\n", addto); + printf(" jmp.w " LABFMT "\n", ftlab2); + //} +} + +/* + * add/sub/... + * + * Param given: + */ +void +hopcode(int f, int o) +{ + char *str; + + switch (o) { + case PLUS: + str = "add"; + break; + case MINUS: + str = "sub"; + break; + case AND: + str = "and"; + break; + case OR: + str = "or"; + break; + case ER: + str = "xor"; + break; + default: + comperr("hopcode2: %d", o); + str = 0; /* XXX gcc */ + } + printf("%s.%c", str, f); +} + +char * +rnames[] = { /* keyed to register number tokens */ + "r0", "r2", "r1", "r3", "a0", "a1", "fb", "sp", "r0h", "r0l", + "r1h", "r1l", +}; + +/* + * Return the size (in bytes) of some types. + */ +int +tlen(p) NODE *p; +{ + switch(p->n_type) { + case CHAR: + case UCHAR: + return(1); + + case INT: + case UNSIGNED: + case FLOAT: + return 2; + + case DOUBLE: + case LONG: + case ULONG: + return 4; + + default: + if (!ISPTR(p->n_type)) + comperr("tlen type %d not pointer"); + return SZPOINT(p->n_type)/SZCHAR; + } +} + +/* + * Emit code to compare two longlong numbers. + */ +static void +twollcomp(NODE *p) +{ + int o = p->n_op; + int s = getlab2(); + int e = p->n_label; + int cb1, cb2; + + if (o >= ULE) + o -= (ULE-LE); + switch (o) { + case NE: + cb1 = 0; + cb2 = NE; + break; + case EQ: + cb1 = NE; + cb2 = 0; + break; + case LE: + case LT: + cb1 = GT; + cb2 = LT; + break; + case GE: + case GT: + cb1 = LT; + cb2 = GT; + break; + + default: + cb1 = cb2 = 0; /* XXX gcc */ + } + if (p->n_op >= ULE) + cb1 += 4, cb2 += 4; + expand(p, 0, " cmp.w UR,UL\n"); + if (cb1) cbgen(cb1, s); + if (cb2) cbgen(cb2, e); + expand(p, 0, " cmp.w AR,AL\n"); + cbgen(p->n_op, e); + deflab(s); +} + + +void +zzzcode(NODE *p, int c) +{ + NODE *l; + + switch (c) { + case 'A': /* print negative shift constant */ + p = getlr(p, 'R'); + if (p->n_op != ICON) + comperr("ZA bad use"); + p->n_lval = -p->n_lval; + adrput(stdout, p); + p->n_lval = -p->n_lval; + break; + + case 'B': + if (p->n_rval) + printf(" add.b #%d,%s\n", + p->n_rval, rnames[STKREG]); + break; + + case 'C': /* Print label address */ + p = p->n_left; + if (p->n_lval) + printf(LABFMT, (int)p->n_lval); + else + printf("%s", p->n_name); + break; + + case 'D': /* copy function pointers */ + l = p->n_left; + printf("\tmov.w #HWRD(%s),%s\n\tmov.w #LWRD(%s),%s\n", + p->n_right->n_name, rnames[l->n_rval+1], + p->n_right->n_name, rnames[l->n_rval]); + break; + + case 'E': /* double-reg printout */ + /* XXX - always r0r2 here */ + printf("%s%s", rnames[R0], rnames[R2]); + break; + + case 'F': /* long comparisions */ + twollcomp(p); + break; + + case 'G': + printf("R0R2"); + break; + + case 'H': /* push 32-bit address (for functions) */ + printf("\tpush.w #HWRD(%s)\n\tpush.w #LWRD(%s)\n", + p->n_left->n_name, p->n_left->n_name); + break; + + case 'I': /* push 32-bit address (for functions) */ + l = p->n_left; + printf("\tpush.w %d[%s]\n\tpush.w %d[%s]\n", + (int)l->n_lval, rnames[l->n_rval], + (int)l->n_lval+2, rnames[l->n_rval]); + break; + + default: + comperr("bad zzzcode %c", c); + } +} + +/*ARGSUSED*/ +int +rewfld(NODE *p) +{ + return(1); +} + +int canaddr(NODE *); +int +canaddr(NODE *p) +{ + int o = p->n_op; + + if (o==NAME || o==REG || o==ICON || o==OREG || + (o==UMUL && shumul(p->n_left, SOREG) == SRDIR)) + return(1); + return(0); +} + +int +fldexpand(NODE *p, int cookie, char **cp) +{ + return 0; +} + +/* + * Does the bitfield shape match? + */ +int +flshape(NODE *p) +{ + int o = p->n_op; + + if (o == OREG || o == REG || o == NAME) + return SRDIR; /* Direct match */ + if (o == UMUL && shumul(p->n_left, SOREG)) + return SROREG; /* Convert into oreg */ + return SRREG; /* put it into a register */ +} + +/* INTEMP shapes must not contain any temporary registers */ +/* XXX should this go away now? */ +int +shtemp(NODE *p) +{ + return 0; +} + +void +adrcon(CONSZ val) +{ + printf("$" CONFMT, val); +} + +void +conput(FILE *fp, NODE *p) +{ + int val = p->n_lval; + + switch (p->n_op) { + case ICON: + if (p->n_name[0] != '\0') { + fprintf(fp, "%s", p->n_name); + if (val) + fprintf(fp, "+%d", val); + } else + fprintf(fp, "%d", val); + return; + + default: + comperr("illegal conput"); + } +} + +/*ARGSUSED*/ +void +insput(NODE *p) +{ + comperr("insput"); +} + +/* + * Write out the upper address, like the upper register of a 2-register + * reference, or the next memory location. + */ +void +upput(NODE *p, int size) +{ + + size /= SZINT; + switch (p->n_op) { + case REG: + fputs(rnames[p->n_rval + 1], stdout); + break; + + case NAME: + case OREG: + p->n_lval += size; + adrput(stdout, p); + p->n_lval -= size; + break; + case ICON: + fprintf(stdout, "#" CONFMT, p->n_lval >> 16); + break; + default: + comperr("upput bad op %d size %d", p->n_op, size); + } +} + +void +adrput(FILE *io, NODE *p) +{ + /* output an address, with offsets, from p */ + + if (p->n_op == FLD) + p = p->n_left; + + switch (p->n_op) { + + case NAME: + if (p->n_name[0] != '\0') + fputs(p->n_name, io); + if (p->n_lval != 0) + fprintf(io, "+" CONFMT, p->n_lval); + return; + + case OREG: + if (p->n_lval) + fprintf(io, "%d", (int)p->n_lval); + fprintf(io, "[%s]", rnames[p->n_rval]); + return; + case ICON: + /* addressable value of the constant */ + fputc('#', io); + conput(io, p); + return; + + case REG: + /*if (DEUNSIGN(p->n_type) == CHAR) { + fprintf(io, "R%c%c", p->n_rval < 2 ? '0' : '1', + (p->n_rval & 1) ? 'H' : 'L'); + } else*/ + fprintf(io, "%s", rnames[p->n_rval]); + return; + + default: + comperr("illegal address, op %d, node %p", p->n_op, p); + return; + + } +} + +static char * +ccbranches[] = { + "jeq", /* jumpe */ + "jne", /* jumpn */ + "jle", /* jumple */ + "jlt", /* jumpl */ + "jge", /* jumpge */ + "jgt", /* jumpg */ + "jleu", /* jumple (jlequ) */ + "jltu", /* jumpl (jlssu) */ + "jgeu", /* jumpge (jgequ) */ + "jgtu", /* jumpg (jgtru) */ +}; + + +/* printf conditional and unconditional branches */ +void +cbgen(int o, int lab) +{ + if (o < EQ || o > UGT) + comperr("bad conditional branch: %s", opst[o]); + printf(" %s " LABFMT "\n", ccbranches[o-EQ], lab); +} + +void +mycanon(NODE *p) +{ +} + +void +myoptim(struct interpass *ip) +{ +} + +#if 0 +void +mygenregs(NODE *p) +{ + + if (p->n_op == MINUS && p->n_type == DOUBLE && + (p->n_su & (LMASK|RMASK)) == (LREG|RREG)) { + p->n_su |= DORIGHT; + } + /* Must walk down correct node first for logops to work */ + if (p->n_op != CBRANCH) + return; + p = p->n_left; + if ((p->n_su & (LMASK|RMASK)) != (LREG|RREG)) + return; + p->n_su &= ~DORIGHT; + +} +#endif + +struct hardops hardops[] = { + { PLUS, FLOAT, "?F_ADD_L04" }, + { MUL, LONG, "?L_MUL_L03" }, + { MUL, ULONG, "?L_MUL_L03" }, + { DIV, LONG, "?SL_DIV_L03" }, + { DIV, ULONG, "?UL_DIV_L03" }, + { MOD, LONG, "?SL_MOD_L03" }, + { MOD, ULONG, "?UL_MOD_L03" }, + { RS, LONGLONG, "__ashrdi3" }, + { RS, ULONGLONG, "__lshrdi3" }, + { LS, LONGLONG, "__ashldi3" }, + { LS, ULONGLONG, "__ashldi3" }, + { 0 }, +}; + +int +special(NODE *p, int shape) +{ + switch (shape) { + case SFTN: + if (ISPTR(p->n_type) && ISFTN(DECREF(p->n_type))) { + if (p->n_op == NAME || p->n_op == OREG) + return SRDIR; + else + return SRREG; + } + break; + } + return SRNOPE; +} + +void +myreader(NODE *p) +{ + NODE *q, *r, *s, *right; + + if (optype(p->n_op) == LTYPE) + return; + if (optype(p->n_op) != UTYPE) + myreader(p->n_right); + myreader(p->n_left); + + switch (p->n_op) { + case PLUS: + case MINUS: + if (p->n_type != LONG && p->n_type != ULONG) + break; + if (p->n_right->n_op == NAME || p->n_right->n_op == OREG) + break; + /* Must convert right into OREG */ + right = p->n_right; + q = mklnode(OREG, BITOOR(freetemp(szty(right->n_type))), + FPREG, right->n_type); + s = mkbinode(ASSIGN, q, right, right->n_type); + r = talloc(); + *r = *q; + p->n_right = r; + pass2_compile(ipnode(s)); + break; + } +} + + +void +rmove(int s, int d, TWORD t) +{ + switch (t) { + case CHAR: + case UCHAR: + printf(" mov.b %s,%s\n", rnames[s], rnames[d]); + break; + default: + printf(" mov.w %s,%s\n", rnames[s], rnames[d]); + } +} + +/* + * For class c, find worst-case displacement of the number of + * registers in the array r[] indexed by class. + */ +int +COLORMAP(int c, int *r) +{ + int num; + + switch (c) { + case CLASSA: + num = r[CLASSA]; + num += r[CLASSC]; + return num < 4; + case CLASSB: + num = r[CLASSB]; + return num < 2; + case CLASSC: + num = 2*r[CLASSA]; + num += r[CLASSC]; + return num < 4; + } + return 0; /* XXX gcc */ +} + +/* + * Return a class suitable for a specific type. + */ +int +gclass(TWORD t) +{ + if (t == CHAR || t == UCHAR) + return CLASSC; + + if(ISPTR(t)) + return CLASSB; + + return CLASSA; +} + +static int sizen; + +/* XXX: Fix this. */ +static int +argsiz(NODE *p) +{ + TWORD t = p->n_type; + + if (t < LONGLONG || t > MAXTYPES) + return 4; + if (t == LONGLONG || t == ULONGLONG || t == DOUBLE) + return 8; + if (t == LDOUBLE) + return 12; + if (t == STRTY) + return p->n_stsize; + comperr("argsiz"); + return 0; +} + +/* + * Calculate argument sizes. + * XXX: Fix this. + */ +void +lastcall(NODE *p) +{ + sizen = 0; + for (p = p->n_right; p->n_op == CM; p = p->n_left) + sizen += argsiz(p->n_right); + sizen += argsiz(p); +} + +/* + * Target-dependent command-line options. + */ +void +mflags(char *str) +{ +} +/* + * Do something target-dependent for xasm arguments. + * Supposed to find target-specific constraints and rewrite them. + */ +int +myxasm(struct interpass *ip, NODE *p) +{ + return 0; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/m16c/macdefs.h b/compilers/pcc/pcc-1.0.0/arch/m16c/macdefs.h new file mode 100644 index 00000000..b59e7661 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/m16c/macdefs.h @@ -0,0 +1,196 @@ +/* $Id: macdefs.h,v 1.23 2007/11/16 22:23:04 gmcgarry Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Machine-dependent defines for both passes. + */ +#define makecc(val,i) lastcon = (lastcon<<8)|((val<<8)>>8); + +#define ARGINIT 40 /* # bits above fp where arguments start */ +#define AUTOINIT 0 /* # bits below fp where automatics start */ + +/* + * Convert (multi-)character constant to integer. + * Assume: If only one value; store at left side (char size), otherwise + * treat it as an integer. + */ + +/* + * Storage space requirements + */ +#define SZCHAR 8 +#define SZINT 16 +#define SZFLOAT 16 +#define SZDOUBLE 16 +#define SZLDOUBLE 16 +#define SZLONG 32 +#define SZSHORT 16 +#define SZLONGLONG 32 +/* pointers are of different sizes on m16c */ +#define SZPOINT(t) (ISFTN(DECREF(t)) ? 32 : 16) + +/* + * Alignment constraints + */ +#define ALCHAR 8 +#define ALINT 16 +#define ALFLOAT 16 +#define ALDOUBLE 16 +#define ALLDOUBLE 16 +#define ALLONG 16 +#define ALLONGLONG 16 +#define ALSHORT 16 +#define ALPOINT 16 +#define ALSTRUCT 16 +#define ALSTACK 16 + +/* + * Min/max values. + */ +#define MIN_CHAR -128 +#define MAX_CHAR 127 +#define MAX_UCHAR 255 +#define MIN_SHORT -32768 +#define MAX_SHORT 32767 +#define MAX_USHORT 65535 +#define MIN_INT -32768 +#define MAX_INT 32767 +#define MAX_UNSIGNED 65535 +#define MIN_LONG -2147483648 +#define MAX_LONG 2147483647 +#define MAX_ULONG 4294967295UL +#define MIN_LONGLONG -2147483648 +#define MAX_LONGLONG 2147483647 +#define MAX_ULONGLONG 4294967295UL + +/* Default char is unsigned */ +#undef CHAR_UNSIGNED + +/* + * Use large-enough types. + */ +typedef long long CONSZ; +typedef unsigned long long U_CONSZ; +typedef long long OFFSZ; + +#define CONFMT "%lld" /* format for printing constants */ +#define LABFMT "L%d" /* format for printing labels */ + +#define BACKAUTO /* stack grows negatively for automatics */ +#define BACKTEMP /* stack grows negatively for temporaries */ + +#undef FIELDOPS /* no bit-field instructions */ +#define RTOLBYTES /* bytes are numbered right to left */ + +/* Definitions mostly used in pass2 */ + +#define BYTEOFF(x) 1 +#define BITOOR(x) ((x)/SZCHAR) /* bit offset to oreg offset */ + +#define STOARG(p) +#define STOFARG(p) +#define STOSTARG(p) +#define genfcall(a,b) gencall(a,b) + +#define szty(t) (((t) == LONG || (t) == ULONG || \ + (ISPTR(t) && ISFTN(DECREF(t)))) ? 2 : 1) + +/* + * m16c register classes: + * A - 16-bit data registers R0-R3 + * B - 16-bit address registers A0-A1 + * C - 8-bit data registers R0H, R0L, R1H, R1L + */ + +#define R0 0 +#define R2 1 +#define R1 2 +#define R3 3 + +#define A0 4 +#define A1 5 +#define FB 6 +#define SP 7 + +#define R0H 8 +#define R0L 9 +#define R1H 10 +#define R1L 11 + +#define NUMCLASS 4 /* Number of register classes */ + +#define RETREG(x) (x == CHAR || x == UCHAR ? R0L : R0) + +#define FPREG FB /* frame pointer */ +#define STKREG SP /* stack pointer */ + +#if 0 +#define REGSZ 8 /* Number of registers */ +#define MINRVAR R1 /* first register variable */ +#define MAXRVAR R2 /* last register variable */ +#endif + +#define MAXREGS 12 /* 12 registers */ + +#define RSTATUS \ + SAREG|TEMPREG, SAREG|PERMREG, SAREG|TEMPREG, SAREG|PERMREG, \ + SBREG|TEMPREG, SBREG|PERMREG, 0, 0, SCREG, SCREG, SCREG, SCREG, + +#define ROVERLAP \ + {R0H, R0L, -1},\ + {-1},\ + {R1H, R1L, -1},\ + {-1},\ +\ + {-1},\ + {-1},\ +\ + {-1},\ + {-1},\ +\ + {R0, -1},\ + {R0, -1},\ + {R1, -1},\ + {R1, -1}, + +#define PCLASS(p) (p->n_type <= UCHAR ? SCREG : ISPTR(p->n_type) ? SBREG:SAREG) + +int COLORMAP(int c, int *r); +#define GCLASS(x) (x < 4 ? CLASSA : x < 6 ? CLASSB : x < 12 ? CLASSC : CLASSD) +#define DECRA(x,y) (((x) >> (y*6)) & 63) /* decode encoded regs */ +#define ENCRD(x) (x) /* Encode dest reg in n_reg */ +#define ENCRA1(x) ((x) << 6) /* A1 */ +#define ENCRA2(x) ((x) << 12) /* A2 */ +#define ENCRA(x,y) ((x) << (6+y*6)) /* encode regs in int */ + +#define MYADDEDGE(x, t) + +#ifndef NEW_READER +//#define TAILCALL +#endif +#define SFTN (SPECIAL|6) diff --git a/compilers/pcc/pcc-1.0.0/arch/m16c/order.c b/compilers/pcc/pcc-1.0.0/arch/m16c/order.c new file mode 100644 index 00000000..13f99d3e --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/m16c/order.c @@ -0,0 +1,621 @@ +/* $Id: order.c,v 1.20 2008/09/27 07:35:23 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass2.h" +# include + +int canaddr(NODE *); + +/* + * should the assignment op p be stored, + * given that it lies as the right operand of o + * (or the left, if o==UNARY MUL) + */ +/* +void +stoasg(NODE *p, int o) +{ + if (x2debug) + printf("stoasg(%p, %o)\n", p, o); +} +*/ +/* should we delay the INCR or DECR operation p */ +int +deltest(NODE *p) +{ + return 0; +} + +/* + * Check if p can be autoincremented. + * XXX - nothing can be autoincremented for now. + */ +int +autoincr(NODE *p) +{ + return 0; +} + +/* is it legal to make an OREG or NAME entry which has an + * offset of off, (from a register of r), if the + * resulting thing had type t */ +int +notoff(TWORD t, int r, CONSZ off, char *cp) +{ + return(0); /* YES */ +} + +/* + * Turn a UMUL-referenced node into OREG. + */ +int +offstar(NODE *p, int shape) +{ + if (x2debug) + printf("offstar(%p)\n", p); + + if( p->n_op == PLUS || p->n_op == MINUS ){ + if( p->n_right->n_op == ICON ){ + geninsn(p->n_left, INBREG); + p->n_su = -1; + return 1; + } + } + geninsn(p, INBREG); + return 0; +} + +/* + * Shape matches for UMUL. Cooperates with offstar(). + */ +int +shumul(NODE *p, int shape) +{ +// NODE *l = p->n_left; + +#ifdef PCC_DEBUG + if (x2debug) { + printf("shumul(%p)\n", p); + fwalk(p, e2print, 0); + } +#endif + /* XXX - fix */ + + /* Can only generate OREG of BREGs (or FB) */ + if (p->n_op == REG && (isbreg(p->n_rval) || p->n_rval == FB)) + return SROREG; +#if 0 + if ((p->n_op == PLUS || p->n_op == MINUS) && + (l->n_op == REG && (isbreg(l->n_rval) || l->n_rval == FB)) && + p->n_right->n_op == ICON) + return SOREG; + return 0; +#else + return SROREG; +#endif +} + +/* + * Rewrite increment/decrement operation. + */ +int +setincr(NODE *p) +{ + if (x2debug) + printf("setincr(%p)\n", p); + + return(0); +} + +/* + * Rewrite operations on binary operators (like +, -, etc...). + * Called as a result of table lookup. + */ +int +setbin(NODE *p) +{ + + if (x2debug) + printf("setbin(%p)\n", p); + return 0; + +} + +/* setup for assignment operator */ +int +setasg(NODE *p, int cookie) +{ + if (x2debug) + printf("setasg(%p)\n", p); + return(0); +} + +/* setup for unary operator */ +int +setuni(NODE *p, int cookie) +{ + return 0; +} + +#if 0 +/* + * register allocation for instructions with special preferences. + */ +regcode +regalloc(NODE *p, struct optab *q, int wantreg) +{ + regcode regc; + + if (q->op == DIV || q->op == MOD) { + /* + * 16-bit div. + */ + if (regblk[R0] & 1 || regblk[R2] & 1) + comperr("regalloc: needed regs inuse, node %p", p); + if (p->n_su & DORIGHT) { + regc = alloregs(p->n_right, A0); + if (REGNUM(regc) != A0) { + p->n_right = movenode(p->n_right, A0); + if ((p->n_su & RMASK) == ROREG) { + p->n_su &= ~RMASK; + p->n_su |= RREG; + p->n_right->n_su &= ~LMASK; + p->n_right->n_su |= LOREG; + } + freeregs(regc); + regblk[A0] |= 1; + } + } + regc = alloregs(p->n_left, R0); + if (REGNUM(regc) != R0) { + p->n_left = movenode(p->n_left, R0); + freeregs(regc); + regblk[R0] |= 1; + } + if ((p->n_su & RMASK) && !(p->n_su & DORIGHT)) { + regc = alloregs(p->n_right, A0); + if (REGNUM(regc) != A0) { + p->n_right = movenode(p->n_right, A0); + if ((p->n_su & RMASK) == ROREG) { + p->n_su &= ~RMASK; + p->n_su |= RREG; + p->n_right->n_su &= ~LMASK; + p->n_right->n_su |= LOREG; + } + } + } + regblk[A0] &= ~1; + regblk[R0] &= ~1; + regblk[R2] &= ~1; + if (q->op == DIV) { + MKREGC(regc, R0, 1); + regblk[R0] |= 1; + } else { + MKREGC(regc, R2, 1); + regblk[R2] |= 1; + } + } else + comperr("regalloc"); + p->n_rall = REGNUM(regc); + return regc; +} +#endif + +/* + * Special handling of some instruction register allocation. + * - left is the register that left node wants. + * - right is the register that right node wants. + * - res is in which register the result will end up. + * - mask is registers that will be clobbered. + * + * XXX - Fix this function + */ +struct rspecial * +nspecial(struct optab *q) +{ + switch (q->op) { + + case DIV: + case MOD: + if(q->ltype & (TINT|TSHORT)){ + static struct rspecial s[] = { + { NRES, R0 }, { NRES, R2}, { 0 } }; + return s; + } + /* + else if(q->ltype & TCHAR) { + static struct rspecial s[] = { + { NRES, R0L }, { NRES, R0H}, { 0 } }; + return s; + }*/ + break; + + case MUL: + /* + if(q->ltype & (TINT|TSHORT)){ + static struct rspecial s[] = { + { NRES, R0 }, { NRES, R2}, { 0 } }; + return s; + }*/ + comperr("multiplication not implemented"); + break; + + default: + break; + } + comperr("nspecial entry %d", q - table); + return 0; /* XXX gcc */ +} + + +/* + * Splitup a function call and give away its arguments first. + * Calling convention used ("normal" in IAR syntax) is: + * - 1-byte parameters in R0L if possible, otherwise in R0H. + * - 2-byte pointers in A0. + * - 2-byte non-pointers in R0 if no byte-size arguments are found in + * in the first 6 bytes of parameters, otherwise R2 or at last A0. + * - 4-byte parameters in R2R0. + */ +void +gencall(NODE *p, NODE *prev) +{ + NODE *n = 0; /* XXX gcc */ + static int storearg(NODE *); + int o = p->n_op; + int ty = optype(o); + + if (ty == LTYPE) + return; + + switch (o) { + case CALL: + /* swap arguments on some hardop-converted insns */ + /* Normal call, just push args and be done with it */ + p->n_op = UCALL; +//printf("call\n"); + /* Check if left can be evaluated directly */ + if (p->n_left->n_op == UMUL) { + TWORD t = p->n_left->n_type; + int k = BITOOR(freetemp(szty(t))); + NODE *n = mklnode(OREG, k, FB, t); + NODE *q = tcopy(n); + pass2_compile(ipnode(mkbinode(ASSIGN, n, p->n_left,t))); + p->n_left = q; + } + gencall(p->n_left, p); + p->n_rval = storearg(p->n_right); +//printf("end call\n"); + break; + + case UFORTCALL: + case FORTCALL: + comperr("FORTCALL"); + + case USTCALL: + case STCALL: + /* + * Structure return. Look at the node above + * to decide about buffer address: + * - FUNARG, allocate space on stack, don't remove. + * - nothing, allocate space on stack and remove. + * - STASG, get the address of the left side as arg. + * - FORCE, this ends up in a return, get supplied addr. + * (this is not pretty, but what to do?) + */ + if (prev == NULL || prev->n_op == FUNARG) { + /* Create nodes to generate stack space */ + n = mkbinode(ASSIGN, mklnode(REG, 0, STKREG, INT), + mkbinode(MINUS, mklnode(REG, 0, STKREG, INT), + mklnode(ICON, p->n_stsize, 0, INT), INT), INT); +//printf("stsize %d\n", p->n_stsize); + pass2_compile(ipnode(n)); + } else if (prev->n_op == STASG) { + n = prev->n_left; + if (n->n_op == UMUL) + n = nfree(n); + else if (n->n_op == NAME) { + n->n_op = ICON; /* Constant reference */ + n->n_type = INCREF(n->n_type); + } else + comperr("gencall stasg"); + } else if (prev->n_op == FORCE) { + ; /* do nothing here */ + } else { + comperr("gencall bad op %d", prev->n_op); + } + + /* Deal with standard arguments */ + gencall(p->n_left, p); + if (o == STCALL) { + p->n_op = USTCALL; + p->n_rval = storearg(p->n_right); + } else + p->n_rval = 0; + /* push return struct address */ + if (prev == NULL || prev->n_op == FUNARG) { + n = mklnode(REG, 0, STKREG, INT); + if (p->n_rval) + n = mkbinode(PLUS, n, + mklnode(ICON, p->n_rval, 0, INT), INT); + pass2_compile(ipnode(mkunode(FUNARG, n, 0, INT))); + if (prev == NULL) + p->n_rval += p->n_stsize/4; + } else if (prev->n_op == FORCE) { + /* return value for this function */ + n = mklnode(OREG, 8, FPREG, INT); + pass2_compile(ipnode(mkunode(FUNARG, n, 0, INT))); + p->n_rval++; + } else { + pass2_compile(ipnode(mkunode(FUNARG, n, 0, INT))); + n = p; + *prev = *p; + nfree(n); + } +//printf("end stcall\n"); + break; + + default: + if (ty != UTYPE) + gencall(p->n_right, p); + gencall(p->n_left, p); + break; + } +} + +/* + * Create separate node trees for function arguments. + * This is partly ticky, the strange calling convention + * may cause a bunch of code reorganization here. + */ +static int +storearg(NODE *p) +{ + NODE *n, *q, **narry; + int nch, k, i, nn, rary[4]; + int r0l, r0h, r2, a0, stk, sz; + TWORD t; + int maxrargs = 0; + + if (p->n_op == CM) + maxrargs = p->n_stalign; + + /* count the arguments */ + for (i = 1, q = p; q->n_op == CM; q = q->n_left) + i++; + nn = i; + + /* allocate array to store arguments */ + narry = tmpalloc(sizeof(NODE *)*nn); + + /* enter nodes into array */ + for (q = p; q->n_op == CM; q = q->n_left) + narry[--i] = q->n_right; + narry[--i] = q; + + /* free CM nodes */ + for (q = p; q->n_op == CM; ) { + n = q->n_left; + nfree(q); + q = n; + } + + /* count char args */ + r0l = r0h = r2 = a0 = 0; + for (sz = nch = i = 0; i < nn && i < 6; i++) { + TWORD t = narry[i]->n_type; + if (sz >= 6) + break; + if (t == CHAR || t == UCHAR) { + nch++; + sz++; + } else if ((t >= SHORT && t <= UNSIGNED) || + t > BTMASK || t == FLOAT) { + sz += 2; + } else /* long, double */ + sz += 4; + + } + + /* + * Now the tricky part. The parameters that should be on stack + * must be found and pushed first, then the register parameters. + * For the latter, be sure that evaluating them do not use any + * registers where argument values already are inserted. + * XXX - function pointers? + * XXX foo(long a, char b) ??? + */ + for (stk = 0; stk < 4; stk++) { + TWORD t; + + if (stk == nn) + break; + t = narry[stk]->n_type; + if (ISFTN(DECREF(t))) + t = LONG; + switch (t) { + case CHAR: case UCHAR: + if (r0l) { + if (r0h) + break; + rary[stk] = R2; /* char talk for 'R0H' */ + r0h = 1; + } else { + rary[stk] = R0; + r0l = 1; + } + continue; + + case INT: case UNSIGNED: + if (r0l || nch) { + if (r2) { + if (a0) + break; + rary[stk] = A0; + a0 = 1; + } else { + rary[stk] = R2; + r2 = 1; + } + } else { + rary[stk] = R0; + r0l = r0h = 1; + } + continue; + + case LONG: case ULONG: + if (r0l || r2) + break; + rary[stk] = R0; + r0l = r0h = r2 = 1; + continue; + + default: + if (ISPTR(narry[stk]->n_type) && + !ISFTN(DECREF(narry[stk]->n_type))) { + if (a0) { + if (r0l || nch) { + if (r2) + break; + rary[stk] = R2; + r2 = 1; + } else { + rary[stk] = R0; + r0l = r0h = 1; + } + } else { + rary[stk] = A0; + a0 = 1; + } + continue; + } + break; + } + break; + } + + /* + * The arguments that must be on stack are stk->nn args. + * Argument 0->stk-1 should be put in the rary[] register. + */ + for (sz = 0, i = nn-1; i >= stk; i--) { /* first stack args */ + NODE nod; + pass2_compile(ipnode(mkunode(FUNARG, + narry[i], 0, narry[i]->n_type))); + nod.n_type = narry[i]->n_type; + sz += tlen(&nod); + } + /* if param cannot be addressed directly, evaluate and put on stack */ + for (i = 0; i < stk; i++) { + + if (canaddr(narry[i])) + continue; + t = narry[i]->n_type; + k = BITOOR(freetemp(szty(t))); + n = mklnode(OREG, k, FB, t); + q = tcopy(n); + pass2_compile(ipnode(mkbinode(ASSIGN, n, narry[i], t))); + narry[i] = q; + } + /* move args to registers */ + for (i = 0; i < stk; i++) { + t = narry[i]->n_type; + pass2_compile(ipnode(mkbinode(ASSIGN, + mklnode(REG, 0, rary[i], t), narry[i], t))); + } + return sz; +} + +/* + * Tell if a register can hold a specific datatype. + */ +#if 0 +int +mayuse(int reg, TWORD type) +{ + return 1; /* Everything is OK */ +} +#endif + +#ifdef TAILCALL +void +mktailopt(struct interpass *ip1, struct interpass *ip2) +{ + extern int earlylab; + extern char *cftname; + char *fn; + NODE *p; + + p = ip1->ip_node->n_left->n_left; + if (p->n_op == ICON) { + fn = p->n_name; + /* calling ourselves */ + p = ip1->ip_node->n_left; + if (p->n_op == CALL) { + if (storearg(p->n_right)) + comperr("too many args: fix mktailopt"); + p->n_op = UCALL; + } + tfree(ip1->ip_node); + p = ip2->ip_node->n_left; + if (strcmp(fn, cftname)) { + /* Not us, must generate fake prologue */ + ip1->type = IP_ASM; + ip1->ip_asm = "mov.w FB,SP\n\tpop.w FB"; + pass2_compile(ip1); + p->n_lval = p->n_rval = 0; + p->n_name = fn; + } else + p->n_lval = earlylab; + } else { + pass2_compile(ip1); + } + pass2_compile(ip2); +} +#endif +/* + * Set registers "live" at function calls (like arguments in registers). + * This is for liveness analysis of registers. + */ +int * +livecall(NODE *p) +{ + static int r[1] = { -1 }; /* Terminate with -1 */ + + return &r[0]; +} + +/* + * Signal whether the instruction is acceptable for this target. + */ +int +acceptable(struct optab *op) +{ + return 1; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/m16c/table.c b/compilers/pcc/pcc-1.0.0/arch/m16c/table.c new file mode 100644 index 00000000..0d09388d --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/m16c/table.c @@ -0,0 +1,587 @@ +#include "pass2.h" + +# define ANYSIGNED TINT|TLONG|TCHAR +# define ANYUSIGNED TUNSIGNED|TULONG|TUCHAR +# define ANYFIXED ANYSIGNED|ANYUSIGNED +# define TL TLONG|TULONG +# define TWORD TUNSIGNED|TINT +# define TCH TCHAR|TUCHAR + +struct optab table[] = { +/* First entry must be an empty entry */ +{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", }, + +/* (signed) char -> int/pointer */ +{ SCONV, INAREG, + SCREG, TCHAR, + SANY, TINT|TPOINT, + NAREG, RESC1, + " mov.b AL, A1\n\texts.b A1\n", }, + +/* (unsigned) char -> int/pointer */ +{ SCONV, INAREG, + SCREG, TUCHAR, + SANY, TINT|TPOINT, + NAREG, RESC1, + " mov.b AL, A1\n", }, + +/* unsigned char -> long */ +{ SCONV, INAREG, + SCREG, TUCHAR, + SANY, TL, + NAREG|NASL, RESC1, + " mov.b AL, A1\n mov.w #0,U1\n", }, + +/* int or pointer -> (unsigned) long */ +{ SCONV, INAREG, + SAREG|SNAME, TWORD|TPOINT, + SANY, TL, + NAREG|NASL, RESC1, + " mov.w AL,A1\n mov.w #0,U1\n", }, + +/* char -> (signed) long */ +{ SCONV, INAREG, + SAREG|SNAME, TCHAR, + SANY, TLONG, + NAREG|NASL, RESC1, + " exts.b AL\n exts.w AL\n", }, + +/* long -> ulong */ +{ SCONV, INAREG, + SAREG, TL, + SANY, TL, + 0, RLEFT, + "", }, + +/* long -> int or pointer */ +{ SCONV, INAREG, + SAREG|SOREG|SNAME, TL, + SANY, TWORD|TPOINT, + NAREG|NASL, RESC1, + " mov.w AL,A1\n", }, + +/* int -> char */ +{ SCONV, INCREG, + SAREG, TWORD, + SANY, TCH, + NCREG, RESC1, + " mov.b AL, A1\n", }, + +/* int -> long */ +{ SCONV, INAREG, + SAREG, TWORD, + SANY, TLONG, + NAREG|NASL, RESC1, + " exts.w AL", }, + +/* long -> char */ +{ SCONV, INAREG, + SAREG, TL, + SANY, TCH, + NAREG|NASL, RESC1, + "", }, + +{ SCONV, INAREG, + SAREG, TPOINT, + SANY, TWORD, + 0, RLEFT, + "", }, + +{ PLUS, INAREG|FOREFF, + SAREG, TL, + SCON|SNAME|SOREG, TL, + 0, RLEFT, + " add.w AR,AL\n adc.w UR,UL\n", }, + +{ MINUS, INAREG|FOREFF, + SAREG, TL, + SCON|SNAME|SOREG, TL, + 0, RLEFT, + " sub.w AR,AL\n sbb.w UR,UL\n", }, + +{ AND, INAREG|FOREFF, + SAREG, TL, + SAREG|SNAME|SOREG, TL, + 0, RLEFT, + " and.w AR,AL\n and.w UR,UL\n", }, + +{ ER, INAREG|FOREFF, + SAREG, TL, + SAREG|SNAME|SOREG, TL, + 0, RLEFT, + " xor.w AR,AL\n xor.w UR,UL\n", }, + +{ OR, INAREG|FOREFF, + SAREG, TL, + SAREG|SNAME|SOREG, TL, + 0, RLEFT, + " xor.w AR,AL\n xor.w UR,UL\n", }, + +{ COMPL, INAREG|FOREFF, + SAREG, TL, + SAREG|SNAME|SOREG, TL, + 0, RLEFT, + " not.w AR,AL\n not.w UR,UL\n", }, + +{ OPSIMP, INAREG|FOREFF, + SAREG, TWORD|TPOINT, + SAREG|SNAME|SOREG|SCON, TWORD|TPOINT, + 0, RLEFT, + " Ow AR,AL\n", }, + +/* XXX - Is this rule really correct? Having a SAREG shape seems kind of + strange. Doesn't work. Gives a areg as A1. */ +#if 0 +{ OPSIMP, INBREG, + SAREG, TWORD|TPOINT, + SAREG|SBREG|SNAME|SOREG|SCON, TWORD|TPOINT, + NBREG, RESC1, + " ++Ow AR,A1\n", }, +#endif + +{ OPSIMP, INBREG, + SBREG, TWORD|TPOINT, + SAREG|SBREG|SNAME|SOREG|SCON, TWORD|TPOINT, + 0, RLEFT, + " Ow AR,AL\n", }, + +{ OPSIMP, INCREG|FOREFF, + SCREG, TCH, + SCREG|SNAME|SOREG|SCON, TCH, + 0, RLEFT, + " Ob AR,AL\n", }, + +/* XXX - Do these work? check nspecial in order.c */ +/* signed integer division */ +{ DIV, INAREG, + SAREG, TINT, + SAREG|SNAME|SOREG, TWORD, + /*2*NAREG|NASL|*/NSPECIAL, RLEFT, + " div.w AR\n mov.w r0,AL\n", }, + // " xor.w r2\n div.w AR\n", }, + + +/* signed integer/char division - separate entry for FOREFF */ +{ DIV, FOREFF, + SAREG, TINT, + SAREG|SNAME|SOREG, TWORD, + 0, 0, + "", }, + +#if 0 +/* signed char division */ +{ DIV, INCREG, + SCREG, TCHAR, + SCREG|SNAME|SOREG, TCH, + 2*NCREG|NCSL|NSPECIAL, RLEFT, + " div.b AR\n\tmov.b r0l,AL\n", }, + // " xor.w r2\n div.w AR\n", }, +#endif + +/* signed integer modulus, equal to above */ +{ MOD, INAREG, + SAREG, TINT, + SAREG|SNAME|SOREG, TWORD, + /*2*NAREG|NASL|*/NSPECIAL, RLEFT, + " div.w AR\n\tmov r2,AL\n", }, + +/* signed integer modulus - separate entry for FOREFF */ +{ MOD, FOREFF, + SAREG, TINT, + SAREG|SNAME|SOREG, TWORD, + 0, 0, + "", }, + +/* signed integer multiplication */ +{ MUL, INAREG, + SAREG, TINT, + SAREG|SNAME|SOREG, TWORD, + 2*NAREG|NASL|NSPECIAL, RESC1, + " mul.w AL,AR\n", }, + +{ MUL, FOREFF, + SAREG, TINT, + SAREG|SNAME|SOREG, TWORD, + 0, 0, + "", }, + +#if 0 +{ LS, INAREG, + SAREG, TWORD, + SCON, TANY, + 0, RLEFT, + " shl.w AR,AL\n", }, +#endif + +{ LS, INAREG, + SAREG, TWORD, + SAREG, TWORD, + 0, RLEFT, + " push.b r1h\n" + " mov.b AR,r1h\n" + " shl.w r1h,AL\n" + " pop.b r1h\n", }, + +{ LS, INAREG, + SAREG, TL, + SAREG, TWORD, + 0, RLEFT, + " push.b r1h\n" + " mov.b AR,r1h\n" + " shl.l r1h,ZG\n" + " pop.b r1h\n", }, + +{ RS, INAREG, + SAREG, TWORD, + SAREG, TWORD, + 0, RLEFT, + " push.b r1h\n" + " mov.b AR,r1h\n" + " neg.b r1h\n" + " shl.w r1h,AL\n" + " pop.b r1h\n", }, + +{ RS, INAREG, + SAREG, TL, + SAREG, TWORD, + 0, RLEFT, + " push.b r1h\n" + " mov.b AR,r1h\n" + " neg.b r1h\n" + " shl.l r1h,ZG\n" + " pop.b r1h\n", }, + +#if 0 +{ RS, INAREG, + SAREG, TUNSIGNED, + SCON, TANY, + 0, RLEFT, + " shl ZA,AL\n", }, + +{ RS, INAREG, + SAREG, TINT, + SCON, TANY, + 0, RLEFT, + " sha ZA,AL\n", }, +#endif + +{ OPLOG, FORCC, + SAREG|SBREG|SOREG|SNAME, TL, + SAREG|SBREG|SOREG|SNAME, TL, + 0, 0, + "ZF", }, + +{ OPLOG, FORCC, + SBREG|SOREG, TWORD|TPOINT, + SCON, TWORD|TPOINT, + 0, RESCC, + " cmp.w AR,AL\n", }, + +{ OPLOG, FORCC, + SAREG|SBREG|SOREG|SNAME, TWORD|TPOINT, + SAREG|SBREG|SOREG|SNAME, TWORD|TPOINT, + 0, RESCC, + " cmp.w AR,AL\n", }, + +{ OPLOG, FORCC, + SCREG|SOREG|SNAME, TCH, + SCREG|SOREG|SNAME, TCH, + 0, RESCC, + " cmp.b AR,AL\n", }, + +{ OPLOG, FORCC, + SCREG|SOREG|SNAME, TCH, + SCREG|SOREG|SNAME, TCH, + 0, RESCC, + " cmp.b AR,AL\n", }, + +{ GOTO, FOREFF, + SCON, TANY, + SANY, TANY, + 0, RNOP, + " jmp.w ZC\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SCON|SNAME|SOREG|SAREG, TL|TFTN, + NAREG, RESC1, + " mov.w AR,A1\n mov.w UR,U1\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SCON|SNAME|SOREG|SAREG|SBREG, TWORD|TPOINT, + NAREG, RESC1, + " mov.w AR,A1\n", }, + +{ OPLTYPE, INBREG, + SANY, TANY, + SBREG|SCON|SNAME|SOREG|SAREG, TWORD|TPOINT, + NBREG, RESC1, + " mov.w AR,A1\n", }, + /* +{ OPLTYPE, INAREG, + SANY, TANY, + SCON|SNAME|SOREG, TCH, + NAREG, RESC1, + " mov.b AR, A1\n", }, + +{ OPLTYPE, INBREG, + SANY, TANY, + SCON|SNAME|SOREG, TCHAR|TUCHAR, + NBREG, RESC1, + " mov.b AR,A1\n", }, + */ + +{ OPLTYPE, INCREG, + SANY, TANY, + SCON|SNAME|SOREG, TCHAR|TUCHAR, + NCREG, RESC1, + " mov.b AR,A1\n", }, + +{ COMPL, INAREG, + SAREG, TWORD, + SANY, TANY, + 0, RLEFT, + " not.w AL\n", }, + +{ COMPL, INCREG, + SCREG, TCH, + SANY, TANY, + 0, RLEFT, + " not.b AL\n", }, + +/* Push function address */ +{ FUNARG, FOREFF, + SCON, TFTN, + SANY, TANY, + 0, RNULL, + "ZH", }, + +{ FUNARG, FOREFF, + SOREG, TFTN, + SANY, TANY, + 0, RNULL, + "ZI", }, + +{ FUNARG, FOREFF, + SNAME|SAREG, TL|TFTN, + SANY, TANY, + 0, RNULL, + " push.w UL\n push.w AL\n", }, + +{ FUNARG, FOREFF, + SCON|SAREG|SNAME|SOREG, TWORD|TPOINT, + SANY, TANY, + 0, RNULL, + " push.w AL\n", }, + +{ FUNARG, FOREFF, + SAREG|SNAME|SOREG, TCHAR|TUCHAR, + SANY, TANY, + 0, RNULL, + " push.b AL\n", }, + +/* Match function pointers first */ +#if 0 +{ ASSIGN, FOREFF, + SFTN, TWORD|TPOINT, + SFTN, TWORD|TPOINT, + NAREG, 0, + "ZD", }, +#endif + +{ ASSIGN, INAREG, + SAREG, TFTN, + SCON, TFTN, + 0, RLEFT, + "ZD", }, + +{ ASSIGN, INBREG, + SBREG, TFTN, + SCON, TFTN, + 0, RLEFT, + "ZD", }, + +{ ASSIGN, INAREG, + SAREG, TFTN, + SBREG|SAREG|SOREG|SNAME, TFTN, + 0, RLEFT, + " mov.w AR,AL\n mov.w UR,UL\n", }, + +{ ASSIGN, INBREG, + SBREG, TFTN, + SBREG|SAREG|SOREG|SNAME, TFTN, + 0, RLEFT, + " mov.w AR,AL\n mov.w UR,UL\n", }, + +{ ASSIGN, INAREG, + SBREG|SAREG|SOREG|SNAME, TFTN, + SAREG, TFTN, + 0, RRIGHT, + " mov.w AR,AL\n mov.w UR,UL\n", }, + +{ ASSIGN, INBREG, + SBREG|SAREG|SOREG|SNAME, TFTN, + SBREG, TFTN, + 0, RRIGHT, + " mov.w AR,AL\n mov.w UR,UL\n", }, + +/* a reg -> a reg */ +{ ASSIGN, FOREFF|INAREG, + SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + 0, RLEFT, + " mov.w AR,AL\n", }, + +{ ASSIGN, INAREG, + SBREG|SAREG|SOREG|SNAME, TL, + SAREG, TL, + 0, RRIGHT, + " mov.w AR,AL\n mov.w UR,UL\n", }, + +{ ASSIGN, INBREG, + SBREG|SAREG|SOREG|SNAME, TL, + SBREG, TL, + 0, RRIGHT, + " mov.w AR,AL\n mov.w UR,UL\n", }, + +{ ASSIGN, FOREFF, + SBREG|SAREG|SOREG|SNAME, TL, + SCON|SBREG|SAREG|SOREG|SNAME, TL, + 0, 0, + " mov.w AR,AL\n mov.w UR,UL\n", }, + +{ ASSIGN, INAREG|FOREFF, + SAREG, TWORD|TPOINT, + SCON, TANY, + 0, RLEFT, + " mov.w AR,AL\n", }, + +{ ASSIGN, INBREG|FOREFF, + SBREG, TWORD|TPOINT, + SCON, TANY, + 0, RLEFT, + " mov.w AR,AL\n", }, + +{ ASSIGN, FOREFF, + SNAME|SOREG, TWORD|TPOINT, + SCON, TANY, + 0, 0, + " mov.w AR,AL\n", }, + +/* char, oreg/name -> c reg */ +{ ASSIGN, FOREFF|INCREG, + SCREG, TCHAR|TUCHAR, + SOREG|SNAME|SCON, TCHAR|TUCHAR, + 0, RLEFT, + " mov.b AR,AL\n", }, + +/* int, oreg/name -> a reg */ +{ ASSIGN, FOREFF|INAREG, + SAREG, TWORD|TPOINT, + SOREG|SNAME, TWORD|TPOINT, + 0, RLEFT, + " mov.w AR,AL\n", }, + +{ ASSIGN, FOREFF|INBREG, + SBREG, TWORD|TPOINT, + SOREG|SNAME, TWORD|TPOINT, + 0, RLEFT, + " mov.w AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SOREG|SNAME, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + 0, RRIGHT, + " mov.w AR,AL\n", }, + +{ ASSIGN, FOREFF|INBREG, + SOREG|SNAME, TWORD|TPOINT, + SBREG, TWORD|TPOINT, + 0, RRIGHT, + " mov.w AR,AL\n", }, + +{ ASSIGN, FOREFF|INCREG, + SOREG|SNAME, TCHAR|TUCHAR, + SCREG, TCHAR|TUCHAR, + 0, RRIGHT, + " mov.b AR,AL\n", }, + +{ ASSIGN, FOREFF|INCREG, + SCREG, TCHAR|TUCHAR, + SCREG, TCHAR|TUCHAR, + 0, RRIGHT, + " mov.b AR,AL\n", }, + +{ ASSIGN, FOREFF|INBREG, + SBREG, TWORD|TPOINT, + SBREG, TWORD|TPOINT, + 0, RRIGHT, + " mov.w AR,AL\n", }, + +{ UMUL, INAREG, + SBREG, TPOINT|TWORD, + SANY, TFTN, + NAREG, RESC1, + " mov.w [AL],A1\n mov.w 2[AL],U1\n", }, + +{ UMUL, INAREG, + SBREG, TPOINT|TWORD, + SANY, TPOINT|TWORD, + NAREG, RESC1, + " mov.w [AL],A1\n", }, + +{ UMUL, INBREG, + SBREG, TPOINT|TWORD, + SANY, TPOINT|TWORD, + NBREG|NBSL, RESC1, + " mov.w [AL],A1\n", }, + +{ UMUL, INAREG, + SBREG, TCHAR|TUCHAR|TPTRTO, + SANY, TCHAR|TUCHAR, + NAREG, RESC1, + " mov.b [AL], A1\n", }, + +{ UCALL, FOREFF, + SCON, TANY, + SANY, TANY, + 0, 0, + " jsr.w CL\nZB", }, + +{ UCALL, INAREG, + SCON, TANY, + SANY, TANY, + NAREG, RESC1, + " jsr.w CL\nZB", }, + +{ UCALL, INAREG, + SNAME|SOREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + " jsri.a AL\nZB", }, + +{ UCALL, FOREFF, + SNAME|SOREG, TANY, + SANY, TANY, + 0, 0, + " jsri.a AL\nZB", }, + +{ UCALL, INAREG, + SBREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + " jsri.a [AL]\nZB", }, + +{ UCALL, FOREFF, + SBREG, TANY, + SANY, TANY, + 0, 0, + " jsri.a [AL]\nZB", }, + + +{ FREE, FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" }, +}; + +int tablesize = sizeof(table)/sizeof(table[0]); + diff --git a/compilers/pcc/pcc-1.0.0/arch/mips/CVS/Entries b/compilers/pcc/pcc-1.0.0/arch/mips/CVS/Entries new file mode 100644 index 00000000..eea4fb2e --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/mips/CVS/Entries @@ -0,0 +1,8 @@ +/TODO/1.2/Thu Dec 13 04:20:14 2007//Tr-1-0-0-RELEASE +/code.c/1.17/Sun Sep 19 14:01:35 2010//Tr-1-0-0-RELEASE +/local.c/1.24/Fri Jan 21 21:47:58 2011//Tr-1-0-0-RELEASE +/local2.c/1.25/Wed Dec 3 22:23:38 2008//Tr-1-0-0-RELEASE +/macdefs.h/1.12/Tue Sep 21 05:43:59 2010//Tr-1-0-0-RELEASE +/order.c/1.12/Sun Nov 30 21:00:24 2008//Tr-1-0-0-RELEASE +/table.c/1.14/Sun Sep 19 13:54:41 2010//Tr-1-0-0-RELEASE +D diff --git a/compilers/pcc/pcc-1.0.0/arch/mips/CVS/Repository b/compilers/pcc/pcc-1.0.0/arch/mips/CVS/Repository new file mode 100644 index 00000000..fb65aa7a --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/mips/CVS/Repository @@ -0,0 +1 @@ +pcc/arch/mips diff --git a/compilers/pcc/pcc-1.0.0/arch/mips/CVS/Root b/compilers/pcc/pcc-1.0.0/arch/mips/CVS/Root new file mode 100644 index 00000000..71e2ccb9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/mips/CVS/Root @@ -0,0 +1 @@ +/cvsroot diff --git a/compilers/pcc/pcc-1.0.0/arch/mips/CVS/Tag b/compilers/pcc/pcc-1.0.0/arch/mips/CVS/Tag new file mode 100644 index 00000000..060fac05 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/mips/CVS/Tag @@ -0,0 +1 @@ +Nr-1-0-0-RELEASE diff --git a/compilers/pcc/pcc-1.0.0/arch/mips/TODO b/compilers/pcc/pcc-1.0.0/arch/mips/TODO new file mode 100644 index 00000000..07072de7 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/mips/TODO @@ -0,0 +1,2 @@ +* Fix floating-point arguments in registers +* Fix structure arguments in registers diff --git a/compilers/pcc/pcc-1.0.0/arch/mips/code.c b/compilers/pcc/pcc-1.0.0/arch/mips/code.c new file mode 100644 index 00000000..79f2140c --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/mips/code.c @@ -0,0 +1,726 @@ +/* $Id: code.c,v 1.17 2010/09/19 14:01:35 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/* + * MIPS port by Jan Enoksson (janeno-1@student.ltu.se) and + * Simon Olsson (simols-1@student.ltu.se) 2005. + */ + +#include +#include "pass1.h" + +/* + * Define everything needed to print out some data (or text). + * This means segment, alignment, visibility, etc. + */ +void +defloc(struct symtab *sp) +{ + static char *loctbl[] = { "text", "data", "section .rodata" }; + static int lastloc = -1; + TWORD t; + char *n; + int s; + + if (sp == NULL) { + lastloc = -1; + return; + } + t = sp->stype; + s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA; + lastloc = s; + if (s == PROG) + return; /* text is written in prologue() */ + if (s != lastloc) + printf(" .%s\n", loctbl[s]); + printf(" .p2align %d\n", ispow2(talign(t, sp->sap))); + n = sp->soname ? sp->soname : sp->sname; + if (sp->sclass == EXTDEF) + printf(" .globl %s\n", n); + if (sp->slevel == 0) { +#ifdef USE_GAS + printf("\t.type %s,@object\n", n); + printf("\t.size %s," CONFMT "\n", n, + tsize(sp->stype, sp->sdf, sp->sap)); +#endif + printf("%s:\n", n); + } else + printf(LABFMT ":\n", sp->soffset); +} + + +#ifdef notdef +/* + * cause the alignment to become a multiple of n + * never called for text segment. + */ +void +defalign(int n) +{ + n = ispow2(n / SZCHAR); + if (n == -1) + cerror("defalign: n != 2^i"); + printf("\t.p2align %d\n", n); +} + +/* + * define the current location as the name p->sname + * never called for text segment. + */ +void +defnam(struct symtab *p) +{ + char *c = p->soname; + + if (p->sclass == EXTDEF) + printf("\t.globl %s\n", c); +#ifdef USE_GAS + printf("\t.type %s,@object\n", c); + printf("\t.size %s," CONFMT "\n", c, tsize(p->stype, p->sdf, p->sap)); +#endif + printf("%s:\n", c); +} +#endif + +static int rvnr; + +/* + * code for the end of a function + * deals with struct return here + */ +void +efcode() +{ + NODE *p, *q; + int tempnr; + int ty; + + if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) + return; + + ty = cftnsp->stype - FTN; + + q = block(REG, NIL, NIL, INCREF(ty), 0, cftnsp->sap); + q->n_rval = V0; + p = tempnode(0, INCREF(ty), 0, cftnsp->sap); + tempnr = regno(p); + p = buildtree(ASSIGN, p, q); + ecomp(p); + + q = tempnode(tempnr, INCREF(ty), 0, cftnsp->sap); + q = buildtree(UMUL, q, NIL); + + p = tempnode(rvnr, INCREF(ty), 0, cftnsp->sap); + p = buildtree(UMUL, p, NIL); + + p = buildtree(ASSIGN, p, q); + ecomp(p); + + q = tempnode(rvnr, INCREF(ty), 0, cftnsp->sap); + p = block(REG, NIL, NIL, INCREF(ty), 0, cftnsp->sap); + p->n_rval = V0; + p = buildtree(ASSIGN, p, q); + ecomp(p); +} + +/* Put a symbol in a temporary + * used by bfcode() and its helpers */ +static void +putintemp(struct symtab *sym) +{ + NODE *p; + p = tempnode(0, sym->stype, sym->sdf, sym->sap); + p = buildtree(ASSIGN, p, nametree(sym)); + sym->soffset = regno(p->n_left); + sym->sflags |= STNODE; + ecomp(p); +} + +/* setup the hidden pointer to struct return parameter + * used by bfcode() */ +static void +param_retptr(void) +{ + NODE *p, *q; + + p = tempnode(0, PTR+STRTY, 0, cftnsp->sap); + rvnr = regno(p); + q = block(REG, NIL, NIL, PTR+STRTY, 0, cftnsp->sap); + q->n_rval = A0; + p = buildtree(ASSIGN, p, q); + ecomp(p); +} + +/* setup struct parameter + * push the registers out to memory + * used by bfcode() */ +static void +param_struct(struct symtab *sym, int *regp) +{ + int reg = *regp; + NODE *p, *q; + int navail; + int sz; + int off; + int num; + int i; + + navail = nargregs - (reg - A0); + sz = tsize(sym->stype, sym->sdf, sym->sap) / SZINT; + off = ARGINIT/SZINT + (reg - A0); + num = sz > navail ? navail : sz; + for (i = 0; i < num; i++) { + q = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + q->n_rval = reg++; + p = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + p->n_rval = FP; + p = block(PLUS, p, bcon(4*off++), INT, 0, MKAP(INT)); + p = block(UMUL, p, NIL, INT, 0, MKAP(INT)); + p = buildtree(ASSIGN, p, q); + ecomp(p); + } + + *regp = reg; +} + +/* setup a 64-bit parameter (double/ldouble/longlong) + * used by bfcode() */ +static void +param_64bit(struct symtab *sym, int *regp, int dotemps) +{ + int reg = *regp; + NODE *p, *q; + int navail; + + /* alignment */ + ++reg; + reg &= ~1; + + navail = nargregs - (reg - A0); + + if (navail < 2) { + /* would have appeared half in registers/half + * on the stack, but alignment ensures it + * appears on the stack */ + if (dotemps) + putintemp(sym); + *regp = reg; + return; + } + + q = block(REG, NIL, NIL, sym->stype, sym->sdf, sym->sap); + q->n_rval = A0A1 + (reg - A0); + if (dotemps) { + p = tempnode(0, sym->stype, sym->sdf, sym->sap); + sym->soffset = regno(p); + sym->sflags |= STNODE; + } else { + p = nametree(sym); + } + p = buildtree(ASSIGN, p, q); + ecomp(p); + *regp = reg + 2; +} + +/* setup a 32-bit param on the stack + * used by bfcode() */ +static void +param_32bit(struct symtab *sym, int *regp, int dotemps) +{ + NODE *p, *q; + + q = block(REG, NIL, NIL, sym->stype, sym->sdf, sym->sap); + q->n_rval = (*regp)++; + if (dotemps) { + p = tempnode(0, sym->stype, sym->sdf, sym->sap); + sym->soffset = regno(p); + sym->sflags |= STNODE; + } else { + p = nametree(sym); + } + p = buildtree(ASSIGN, p, q); + ecomp(p); +} + +/* + * XXX This is a hack. We cannot have (l)doubles in more than one + * register class. So we bounce them in and out of temps to + * move them in and out of the right registers. + */ +static void +param_double(struct symtab *sym, int *regp, int dotemps) +{ + int reg = *regp; + NODE *p, *q, *t; + int navail; + int tmpnr; + + /* alignment */ + ++reg; + reg &= ~1; + + navail = nargregs - (reg - A0); + + if (navail < 2) { + /* would have appeared half in registers/half + * on the stack, but alignment ensures it + * appears on the stack */ + if (dotemps) + putintemp(sym); + *regp = reg; + return; + } + + t = tempnode(0, LONGLONG, 0, MKAP(LONGLONG)); + tmpnr = regno(t); + q = block(REG, NIL, NIL, LONGLONG, 0, MKAP(LONGLONG)); + q->n_rval = A0A1 + (reg - A0); + p = buildtree(ASSIGN, t, q); + ecomp(p); + + if (dotemps) { + sym->soffset = tmpnr; + sym->sflags |= STNODE; + } else { + q = tempnode(tmpnr, sym->stype, sym->sdf, sym->sap); + p = nametree(sym); + p = buildtree(ASSIGN, p, q); + ecomp(p); + } + *regp = reg + 2; +} + +/* + * XXX This is a hack. We cannot have floats in more than one + * register class. So we bounce them in and out of temps to + * move them in and out of the right registers. + */ +static void +param_float(struct symtab *sym, int *regp, int dotemps) +{ + NODE *p, *q, *t; + int tmpnr; + + t = tempnode(0, INT, 0, MKAP(INT)); + tmpnr = regno(t); + q = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + q->n_rval = (*regp)++; + p = buildtree(ASSIGN, t, q); + ecomp(p); + + if (dotemps) { + sym->soffset = tmpnr; + sym->sflags |= STNODE; + } else { + q = tempnode(tmpnr, sym->stype, sym->sdf, sym->sap); + p = nametree(sym); + p = buildtree(ASSIGN, p, q); + ecomp(p); + } +} + +/* + * code for the beginning of a function; a is an array of + * indices in symtab for the arguments; n is the number + */ +void +bfcode(struct symtab **sp, int cnt) +{ + union arglist *usym; + int lastreg = A0 + nargregs - 1; + int saveallargs = 0; + int i, reg; + + /* + * Detect if this function has ellipses and save all + * argument register onto stack. + */ + usym = cftnsp->sdf->dfun; + while (usym && usym->type != TNULL) { + if (usym->type == TELLIPSIS) { + saveallargs = 1; + break; + } + ++usym; + } + + reg = A0; + + /* assign hidden return structure to temporary */ + if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) { + param_retptr(); + ++reg; + } + + /* recalculate the arg offset and create TEMP moves */ + for (i = 0; i < cnt; i++) { + + if ((reg > lastreg) && !xtemps) + break; + else if (reg > lastreg) + putintemp(sp[i]); + else if (sp[i]->stype == STRTY || sp[i]->stype == UNIONTY) + param_struct(sp[i], ®); + else if (DEUNSIGN(sp[i]->stype) == LONGLONG) + param_64bit(sp[i], ®, xtemps && !saveallargs); + else if (sp[i]->stype == DOUBLE || sp[i]->stype == LDOUBLE) + param_double(sp[i], ®, xtemps && !saveallargs); + else if (sp[i]->stype == FLOAT) + param_float(sp[i], ®, xtemps && !saveallargs); + else + param_32bit(sp[i], ®, xtemps && !saveallargs); + } + + /* if saveallargs, save the rest of the args onto the stack */ + if (!saveallargs) + return; + while (reg <= lastreg) { + NODE *p, *q; + int off = ARGINIT/SZINT + (reg - A0); + q = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + q->n_rval = reg++; + p = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + p->n_rval = FP; + p = block(PLUS, p, bcon(4*off), INT, 0, MKAP(INT)); + p = block(UMUL, p, NIL, INT, 0, MKAP(INT)); + p = buildtree(ASSIGN, p, q); + ecomp(p); + } + +} + + +/* + * by now, the automatics and register variables are allocated + */ +void +bccode() +{ + SETOFF(autooff, SZINT); +} + +/* called just before final exit */ +/* flag is 1 if errors, 0 if none */ +void +ejobcode(int flag ) +{ +} + +void +bjobcode() +{ + printf("\t.section .mdebug.abi32\n"); + printf("\t.previous\n"); + printf("\t.abicalls\n"); +} + +#ifdef notdef +/* + * Print character t at position i in one string, until t == -1. + * Locctr & label is already defined. + */ +void +bycode(int t, int i) +{ + static int lastoctal = 0; + + /* put byte i+1 in a string */ + + if (t < 0) { + if (i != 0) + puts("\\000\""); + } else { + if (i == 0) + printf("\t.ascii \""); + if (t == 0) + return; + else if (t == '\\' || t == '"') { + lastoctal = 0; + putchar('\\'); + putchar(t); + } else if (t == 011) { + printf("\\t"); + } else if (t == 012) { + printf("\\n"); + } else if (t < 040 || t >= 0177) { + lastoctal++; + printf("\\%o",t); + } else if (lastoctal && '0' <= t && t <= '9') { + lastoctal = 0; + printf("\"\n\t.ascii \"%c", t); + } else { + lastoctal = 0; + putchar(t); + } + } +} +#endif + +/* + * return the alignment of field of type t + */ +int +fldal(unsigned int t) +{ + uerror("illegal field type"); + return(ALINT); +} + +/* fix up type of field p */ +void +fldty(struct symtab *p) +{ +} + +/* + * XXX - fix genswitch. + */ +int +mygenswitch(int num, TWORD type, struct swents **p, int n) +{ + return 0; +} + + +/* setup call stack with a structure */ +/* called from moveargs() */ +static NODE * +movearg_struct(NODE *p, NODE *parent, int *regp) +{ + int reg = *regp; + NODE *l, *q, *t, *r; + int tmpnr; + int navail; + int off; + int num; + int sz; + int ty; + int i; + + navail = nargregs - (reg - A0); + sz = tsize(p->n_type, p->n_df, p->n_ap) / SZINT; + num = sz > navail ? navail : sz; + + l = p->n_left; + nfree(p); + ty = l->n_type; + t = tempnode(0, l->n_type, l->n_df, l->n_ap); + tmpnr = regno(t); + l = buildtree(ASSIGN, t, l); + + if (p != parent) { + q = parent->n_left; + } else + q = NULL; + + /* copy structure into registers */ + for (i = 0; i < num; i++) { + t = tempnode(tmpnr, ty, 0, MKAP(PTR+ty)); + t = block(SCONV, t, NIL, PTR+INT, 0, MKAP(PTR+INT)); + t = block(PLUS, t, bcon(4*i), PTR+INT, 0, MKAP(PTR+INT)); + t = buildtree(UMUL, t, NIL); + + r = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + r->n_rval = reg++; + + r = buildtree(ASSIGN, r, t); + if (q == NULL) + q = r; + else + q = block(CM, q, r, INT, 0, MKAP(INT)); + } + off = ARGINIT/SZINT + nargregs; + for (i = num; i < sz; i++) { + t = tempnode(tmpnr, ty, 0, MKAP(PTR+ty)); + t = block(SCONV, t, NIL, PTR+INT, 0, MKAP(PTR+INT)); + t = block(PLUS, t, bcon(4*i), PTR+INT, 0, MKAP(PTR+INT)); + t = buildtree(UMUL, t, NIL); + + r = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + r->n_rval = FP; + r = block(PLUS, r, bcon(4*off++), INT, 0, MKAP(INT)); + r = block(UMUL, r, NIL, INT, 0, MKAP(INT)); + + r = buildtree(ASSIGN, r, t); + if (q == NULL) + q = r; + else + q = block(CM, q, r, INT, 0, MKAP(INT)); + } + + if (parent->n_op == CM) { + parent->n_left = q; + q = l; + } else { + q = block(CM, q, l, INT, 0, MKAP(INT)); + } + + *regp = reg; + return q; +} + +/* setup call stack with 64-bit argument */ +/* called from moveargs() */ +static NODE * +movearg_64bit(NODE *p, int *regp) +{ + int reg = *regp; + NODE *q; + int lastarg; + + /* alignment */ + ++reg; + reg &= ~1; + + lastarg = A0 + nargregs - 1; + if (reg > lastarg) { + *regp = reg; + return block(FUNARG, p, NIL, p->n_type, p->n_df, p->n_ap); + } + + q = block(REG, NIL, NIL, p->n_type, p->n_df, p->n_ap); + q->n_rval = A0A1 + (reg - A0); + q = buildtree(ASSIGN, q, p); + + *regp = reg + 2; + return q; +} + +/* setup call stack with 32-bit argument */ +/* called from moveargs() */ +static NODE * +movearg_32bit(NODE *p, int *regp) +{ + int reg = *regp; + NODE *q; + + q = block(REG, NIL, NIL, p->n_type, p->n_df, p->n_ap); + q->n_rval = reg++; + q = buildtree(ASSIGN, q, p); + + *regp = reg; + return q; +} + +static NODE * +moveargs(NODE *p, int *regp) +{ + NODE *r, **rp; + int lastreg; + int reg; + + if (p->n_op == CM) { + p->n_left = moveargs(p->n_left, regp); + r = p->n_right; + rp = &p->n_right; + } else { + r = p; + rp = &p; + } + + lastreg = A0 + nargregs - 1; + reg = *regp; + + if (reg > lastreg && r->n_op != STARG) + *rp = block(FUNARG, r, NIL, r->n_type, r->n_df, r->n_ap); + else if (r->n_op == STARG) { + *rp = movearg_struct(r, p, regp); + } else if (DEUNSIGN(r->n_type) == LONGLONG) { + *rp = movearg_64bit(r, regp); + } else if (r->n_type == DOUBLE || r->n_type == LDOUBLE) { + /* XXX bounce in and out of temporary to change to longlong */ + NODE *t1 = tempnode(0, LONGLONG, 0, MKAP(LONGLONG)); + int tmpnr = regno(t1); + NODE *t2 = tempnode(tmpnr, r->n_type, r->n_df, r->n_ap); + t1 = movearg_64bit(t1, regp); + r = block(ASSIGN, t2, r, r->n_type, r->n_df, r->n_ap); + if (p->n_op == CM) { + p->n_left = buildtree(CM, p->n_left, t1); + p->n_right = r; + } else { + p = buildtree(CM, t1, r); + } + } else if (r->n_type == FLOAT) { + /* XXX bounce in and out of temporary to change to int */ + NODE *t1 = tempnode(0, INT, 0, MKAP(INT)); + int tmpnr = regno(t1); + NODE *t2 = tempnode(tmpnr, r->n_type, r->n_df, r->n_ap); + t1 = movearg_32bit(t1, regp); + r = block(ASSIGN, t2, r, r->n_type, r->n_df, r->n_ap); + if (p->n_op == CM) { + p->n_left = buildtree(CM, p->n_left, t1); + p->n_right = r; + } else { + p = buildtree(CM, t1, r); + } + } else { + *rp = movearg_32bit(r, regp); + } + + return p; +} + +/* + * Called with a function call with arguments as argument. + * This is done early in buildtree() and only done once. + */ +NODE * +funcode(NODE *p) +{ + int regnum = A0; + NODE *l, *r, *t, *q; + int ty; + + l = p->n_left; + r = p->n_right; + + /* + * if returning a structure, make the first argument + * a hidden pointer to return structure. + */ + ty = DECREF(l->n_type); + if (ty == STRTY+FTN || ty == UNIONTY+FTN) { + ty = DECREF(l->n_type) - FTN; + q = tempnode(0, ty, l->n_df, l->n_ap); + q = buildtree(ADDROF, q, NIL); + if (r->n_op != CM) { + p->n_right = block(CM, q, r, INCREF(ty), + l->n_df, l->n_ap); + } else { + for (t = r; t->n_left->n_op == CM; t = t->n_left) + ; + t->n_left = block(CM, q, t->n_left, INCREF(ty), + l->n_df, l->n_ap); + } + } + + p->n_right = moveargs(p->n_right, ®num); + + return p; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/mips/local.c b/compilers/pcc/pcc-1.0.0/arch/mips/local.c new file mode 100644 index 00000000..d959c0da --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/mips/local.c @@ -0,0 +1,926 @@ +/* $Id: local.c,v 1.24 2011/01/21 21:47:58 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * MIPS port by Jan Enoksson (janeno-1@student.ltu.se) and + * Simon Olsson (simols-1@student.ltu.se) 2005. + */ + +#include +#include "pass1.h" + +#define IALLOC(sz) (isinlining ? permalloc(sz) : tmpalloc(sz)) + +static int inbits, inval; + +/* this is called to do local transformations on + * an expression tree preparitory to its being + * written out in intermediate code. + */ +NODE * +clocal(NODE *p) +{ + struct symtab *q; + NODE *r, *l; + int o; + int m; + TWORD ty; + int tmpnr, isptrvoid = 0; + +#ifdef PCC_DEBUG + if (xdebug) { + printf("clocal in: %p\n", p); + fwalk(p, eprint, 0); + } +#endif + + switch (o = p->n_op) { + + case UCALL: + case CALL: + case STCALL: + case USTCALL: + if (p->n_type == VOID) + break; + /* + * if the function returns void*, ecode() invokes + * delvoid() to convert it to uchar*. + * We just let this happen on the ASSIGN to the temp, + * and cast the pointer back to void* on access + * from the temp. + */ + if (p->n_type == PTR+VOID) + isptrvoid = 1; + r = tempnode(0, p->n_type, p->n_df, p->n_ap); + tmpnr = regno(r); + r = block(ASSIGN, r, p, p->n_type, p->n_df, p->n_ap); + + p = tempnode(tmpnr, r->n_type, r->n_df, r->n_ap); + if (isptrvoid) { + p = block(PCONV, p, NIL, PTR+VOID, + p->n_df, MKAP(PTR+VOID)); + } + p = buildtree(COMOP, r, p); + break; + + case NAME: + if ((q = p->n_sp) == NULL) + return p; /* Nothing to care about */ + + switch (q->sclass) { + + case PARAM: + case AUTO: + /* fake up a structure reference */ + r = block(REG, NIL, NIL, PTR+STRTY, 0, 0); + r->n_lval = 0; + r->n_rval = FP; + p = stref(block(STREF, r, p, 0, 0, 0)); + break; + + case STATIC: + if (q->slevel == 0) + break; + p->n_lval = 0; + p->n_sp = q; + break; + + case REGISTER: + p->n_op = REG; + p->n_lval = 0; + p->n_rval = q->soffset; + break; + + } + break; + + case FUNARG: + /* Args smaller than int are given as int */ + if (p->n_type != CHAR && p->n_type != UCHAR && + p->n_type != SHORT && p->n_type != USHORT) + break; + p->n_left = block(SCONV, p->n_left, NIL, INT, 0, MKAP(INT)); + p->n_type = INT; + p->n_ap = MKAP(INT); + p->n_rval = SZINT; + break; + + case CBRANCH: + l = p->n_left; + + /* + * Remove unnecessary conversion ops. + */ + if (clogop(l->n_op) && l->n_left->n_op == SCONV) { + if (coptype(l->n_op) != BITYPE) + break; + if (l->n_right->n_op == ICON) { + r = l->n_left->n_left; + if (r->n_type >= FLOAT && r->n_type <= LDOUBLE) + break; + /* Type must be correct */ + ty = r->n_type; + nfree(l->n_left); + l->n_left = r; + l->n_type = ty; + l->n_right->n_type = ty; + } +#if 0 + else if (l->n_right->n_op == SCONV && + l->n_left->n_type == l->n_right->n_type) { + r = l->n_left->n_left; + nfree(l->n_left); + l->n_left = r; + r = l->n_right->n_left; + nfree(l->n_right); + l->n_right = r; + } +#endif + } + break; + + case PCONV: + /* Remove redundant PCONV's. Be careful */ + l = p->n_left; + if (l->n_op == ICON) { + l->n_lval = (unsigned)l->n_lval; + goto delp; + } + if (l->n_type < INT || DEUNSIGN(l->n_type) == LONGLONG) { + /* float etc? */ + p->n_left = block(SCONV, l, NIL, + UNSIGNED, 0, MKAP(UNSIGNED)); + break; + } + /* if left is SCONV, cannot remove */ + if (l->n_op == SCONV) + break; + + /* avoid ADDROF TEMP */ + if (l->n_op == ADDROF && l->n_left->n_op == TEMP) + break; + + /* if conversion to another pointer type, just remove */ + if (p->n_type > BTMASK && l->n_type > BTMASK) + goto delp; + break; + + delp: l->n_type = p->n_type; + l->n_qual = p->n_qual; + l->n_df = p->n_df; + l->n_ap = p->n_ap; + nfree(p); + p = l; + break; + + case SCONV: + l = p->n_left; + + if (p->n_type == l->n_type) { + nfree(p); + p = l; + break; + } + + if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 && + btattr[p->n_type].atypsz == btattr[l->n_type].atypsz) { + if (p->n_type != FLOAT && p->n_type != DOUBLE && + l->n_type != FLOAT && l->n_type != DOUBLE && + l->n_type != LDOUBLE && p->n_type != LDOUBLE) { + if (l->n_op == NAME || l->n_op == UMUL || + l->n_op == TEMP) { + l->n_type = p->n_type; + nfree(p); + p = l; + break; + } + } + } + + if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT && + coptype(l->n_op) == BITYPE) { + l->n_type = p->n_type; + nfree(p); + p = l; + } + + if (DEUNSIGN(p->n_type) == SHORT && + DEUNSIGN(l->n_type) == SHORT) { + nfree(p); + p = l; + } + + /* convert float/double to int before to (u)char/(u)short */ + if ((DEUNSIGN(p->n_type) == CHAR || + DEUNSIGN(p->n_type) == SHORT) && + (l->n_type == FLOAT || l->n_type == DOUBLE || + l->n_type == LDOUBLE)) { + p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_ap); + p->n_left->n_type = INT; + break; + } + + /* convert (u)char/(u)short to int before float/double */ + if ((p->n_type == FLOAT || p->n_type == DOUBLE || + p->n_type == LDOUBLE) && (DEUNSIGN(l->n_type) == CHAR || + DEUNSIGN(l->n_type) == SHORT)) { + p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_ap); + p->n_left->n_type = INT; + break; + } + + o = l->n_op; + m = p->n_type; + + if (o == ICON) { + CONSZ val = l->n_lval; + + if (!ISPTR(m)) /* Pointers don't need to be conv'd */ + switch (m) { + case BOOL: + l->n_lval = l->n_lval != 0; + break; + case CHAR: + l->n_lval = (char)val; + break; + case UCHAR: + l->n_lval = val & 0377; + break; + case SHORT: + l->n_lval = (short)val; + break; + case USHORT: + l->n_lval = val & 0177777; + break; + case ULONG: + case UNSIGNED: + l->n_lval = val & 0xffffffff; + break; + case LONG: + case INT: + l->n_lval = (int)val; + break; + case LONGLONG: + l->n_lval = (long long)val; + break; + case ULONGLONG: + l->n_lval = val; + break; + case VOID: + break; + case LDOUBLE: + case DOUBLE: + case FLOAT: + l->n_op = FCON; + l->n_dcon = val; + break; + default: + cerror("unknown type %d", m); + } + l->n_type = m; + nfree(p); + p = l; + } else if (o == FCON) { + l->n_lval = l->n_dcon; + l->n_sp = NULL; + l->n_op = ICON; + l->n_type = m; + l->n_ap = MKAP(m); + nfree(p); + p = clocal(l); + } + break; + + case MOD: + case DIV: + if (o == DIV && p->n_type != CHAR && p->n_type != SHORT) + break; + if (o == MOD && p->n_type != CHAR && p->n_type != SHORT) + break; + /* make it an int division by inserting conversions */ + p->n_left = block(SCONV, p->n_left, NIL, INT, 0, MKAP(INT)); + p->n_right = block(SCONV, p->n_right, NIL, INT, 0, MKAP(INT)); + p = block(SCONV, p, NIL, p->n_type, 0, MKAP(p->n_type)); + p->n_left->n_type = INT; + break; + + case PMCONV: + case PVCONV: + if( p->n_right->n_op != ICON ) cerror( "bad conversion", 0); + nfree(p); + p = buildtree(o==PMCONV?MUL:DIV, p->n_left, p->n_right); + break; + + case FORCE: + /* put return value in return reg */ + p->n_op = ASSIGN; + p->n_right = p->n_left; + p->n_left = block(REG, NIL, NIL, p->n_type, 0, MKAP(INT)); + p->n_left->n_rval = RETREG(p->n_type); + break; + } + +#ifdef PCC_DEBUG + if (xdebug) { + printf("clocal out: %p\n", p); + fwalk(p, eprint, 0); + } +#endif + + return(p); +} + +void +myp2tree(NODE *p) +{ + struct symtab *sp; + + if (p->n_op != FCON) + return; + + /* Write float constants to memory */ + + sp = IALLOC(sizeof(struct symtab)); + sp->sclass = STATIC; + sp->sap = MKAP(p->n_type); + sp->slevel = 1; /* fake numeric label */ + sp->soffset = getlab(); + sp->sflags = 0; + sp->stype = p->n_type; + sp->squal = (CON >> TSHIFT); + + defloc(sp); + ninval(0, sp->sap->atypsz, p); + + p->n_op = NAME; + p->n_lval = 0; + p->n_sp = sp; + +} + +/*ARGSUSED*/ +int +andable(NODE *p) +{ + return(1); /* all names can have & taken on them */ +} + +/* + * at the end of the arguments of a ftn, set the automatic offset + */ +void +cendarg() +{ + autooff = AUTOINIT; +} + +/* + * is an automatic variable of type t OK for a register variable + */ +int +cisreg(TWORD t) +{ + if (t == INT || t == UNSIGNED || t == LONG || t == ULONG) + return(1); + return 0; /* XXX - fix reg assignment in pftn.c */ +} + +/* + * return a node, for structure references, which is suitable for + * being added to a pointer of type t, in order to be off bits offset + * into a structure + * t, d, and s are the type, dimension offset, and sizeoffset + * Be careful about only handling first-level pointers, the following + * indirections must be fullword. + */ +NODE * +offcon(OFFSZ off, TWORD t, union dimfun *d, struct attr *sue) +{ + NODE *p; + + if (xdebug) + printf("offcon: OFFSZ %lld type %x dim %p siz %d\n", + off, t, d, 0); + + p = bcon(off/SZCHAR); + return p; +} + +/* + * Allocate off bits on the stack. p is a tree that when evaluated + * is the multiply count for off, t is a NAME node where to write + * the allocated address. + */ +void +spalloc(NODE *t, NODE *p, OFFSZ off) +{ + NODE *sp; + int nbytes = off / SZCHAR; + + p = buildtree(MUL, p, bcon(nbytes)); + p = buildtree(PLUS, p, bcon(7)); + p = buildtree(AND, p, bcon(~7)); + + /* subtract the size from sp */ + sp = block(REG, NIL, NIL, p->n_type, 0, 0); + sp->n_lval = 0; + sp->n_rval = SP; + ecomp(buildtree(MINUSEQ, sp, p)); + + /* save the address of sp */ + sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_ap); + sp->n_rval = SP; + t->n_type = sp->n_type; + ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */ +} + +/* + * print out a constant node + * mat be associated with a label + */ +void +ninval(CONSZ off, int fsz, NODE *p) +{ + union { float f; double d; int i[2]; } u; + struct symtab *q; + TWORD t; +#ifndef USE_GAS + int i, j; +#endif + + t = p->n_type; + if (t > BTMASK) + t = INT; /* pointer */ + + if (p->n_op != ICON && p->n_op != FCON) + cerror("ninval: init node not constant"); + + if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT) + uerror("element not constant"); + + switch (t) { + case LONGLONG: + case ULONGLONG: +#ifdef USE_GAS + printf("\t.dword %lld\n", (long long)p->n_lval); +#else + i = p->n_lval >> 32; + j = p->n_lval & 0xffffffff; + p->n_type = INT; + if (bigendian) { + p->n_lval = j; + ninval(off, 32, p); + p->n_lval = i; + ninval(off+32, 32, p); + } else { + p->n_lval = i; + ninval(off, 32, p); + p->n_lval = j; + ninval(off+32, 32, p); + } +#endif + break; + case BOOL: + if (p->n_lval > 1) + p->n_lval = p->n_lval != 0; + /* FALLTHROUGH */ + case INT: + case UNSIGNED: + printf("\t.word " CONFMT, (CONSZ)p->n_lval); + if ((q = p->n_sp) != NULL) { + if ((q->sclass == STATIC && q->slevel > 0)) { + printf("+" LABFMT, q->soffset); + } else + printf("+%s", + q->soname ? q->soname : exname(q->sname)); + } + printf("\n"); + break; + case SHORT: + case USHORT: + printf("\t.half %d\n", (int)p->n_lval & 0xffff); + break; + case CHAR: + case UCHAR: + printf("\t.byte %d\n", (int)p->n_lval & 0xff); + break; + case LDOUBLE: + case DOUBLE: + u.d = (double)p->n_dcon; + if (bigendian) { + printf("\t.word\t%d\n", u.i[0]); + printf("\t.word\t%d\n", u.i[1]); + } else { + printf("\t.word\t%d\n", u.i[1]); + printf("\t.word\t%d\n", u.i[0]); + } + break; + case FLOAT: + u.f = (float)p->n_dcon; + printf("\t.word\t0x%x\n", u.i[0]); + break; + default: + cerror("ninval"); + } +} + +/* make a name look like an external name in the local machine */ +char * +exname(char *p) +{ + if (p == NULL) + return ""; + return p; +} + +/* + * map types which are not defined on the local machine + */ +TWORD +ctype(TWORD type) +{ + switch (BTYPE(type)) { + case LONG: + MODTYPE(type,INT); + break; + + case ULONG: + MODTYPE(type,UNSIGNED); + + } + return (type); +} + +/* curid is a variable which is defined but + * is not initialized (and not a function ); + * This routine returns the storage class for an uninitialized declaration + */ +int +noinit(void) +{ + return(EXTERN); +} + +void +calldec(NODE *p, NODE *q) +{ +} + +void +extdec(struct symtab *q) +{ +} + +/* + * Print out a string of characters. + * Assume that the assembler understands C-style escape + * sequences. + */ +void +instring(struct symtab *sp) +{ + char *s, *str; + + defloc(sp); + str = sp->sname; + + /* be kind to assemblers and avoid long strings */ + printf("\t.ascii \""); + for (s = str; *s != 0; ) { + if (*s++ == '\\') { + (void)esccon(&s); + } + if (s - str > 60) { + fwrite(str, 1, s - str, stdout); + printf("\"\n\t.ascii \""); + str = s; + } + } + fwrite(str, 1, s - str, stdout); + printf("\\0\"\n"); +} + +/* make a common declaration for id, if reasonable */ +void +defzero(struct symtab *sp) +{ + int off; + + off = tsize(sp->stype, sp->sdf, sp->sap); + off = (off+(SZCHAR-1))/SZCHAR; + printf(" .%scomm ", sp->sclass == STATIC ? "l" : ""); + if (sp->slevel == 0) + printf("%s,0%o\n", sp->soname ? sp->soname : exname(sp->sname), off); + else + printf(LABFMT ",0%o\n", sp->soffset, off); +} + + +#ifdef notdef +/* make a common declaration for id, if reasonable */ +void +commdec(struct symtab *q) +{ + int off; + + off = tsize(q->stype, q->sdf, q->ssue); + off = (off+(SZCHAR-1))/SZCHAR; + + printf(" .comm %s,%d\n", exname(q->soname), off); +} + +/* make a local common declaration for id, if reasonable */ +void +lcommdec(struct symtab *q) +{ + int off; + + off = tsize(q->stype, q->sdf, q->ssue); + off = (off+(SZCHAR-1))/SZCHAR; + if (q->slevel == 0) + printf("\t.lcomm %s,%d\n", exname(q->soname), off); + else + printf("\t.lcomm " LABFMT ",%d\n", q->soffset, off); +} + +/* + * print a (non-prog) label. + */ +void +deflab1(int label) +{ + printf(LABFMT ":\n", label); +} + +/* ro-text, rw-data, ro-data, ro-strings */ +static char *loctbl[] = { "text", "data", "rdata", "rdata" }; + +void +setloc1(int locc) +{ + if (locc == lastloc && locc != STRNG) + return; + if (locc == RDATA && lastloc == STRNG) + return; + + if (locc != lastloc) { + lastloc = locc; + printf("\t.%s\n", loctbl[locc]); + } + + if (locc == STRNG) + printf("\t.align 2\n"); +} +#endif + +/* + * Initialize a bitfield. + */ +void +infld(CONSZ off, int fsz, CONSZ val) +{ + if (idebug) + printf("infld off %lld, fsz %d, val %lld inbits %d\n", + off, fsz, val, inbits); + val &= (1 << fsz)-1; + while (fsz + inbits >= SZCHAR) { + inval |= (val << inbits); + printf("\t.byte %d\n", inval & 255); + fsz -= (SZCHAR - inbits); + val >>= (SZCHAR - inbits); + inval = inbits = 0; + } + if (fsz) { + inval |= (val << inbits); + inbits += fsz; + } +} + +/* + * set fsz bits in sequence to zero. + */ +void +zbits(OFFSZ off, int fsz) +{ + int m; + + if (idebug) + printf("zbits off %lld, fsz %d inbits %d\n", off, fsz, inbits); + if ((m = (inbits % SZCHAR))) { + m = SZCHAR - m; + if (fsz < m) { + inbits += fsz; + return; + } else { + fsz -= m; + printf("\t.byte %d\n", inval); + inval = inbits = 0; + } + } + if (fsz >= SZCHAR) { + printf("\t.zero %d\n", fsz/SZCHAR); + fsz -= (fsz/SZCHAR) * SZCHAR; + } + if (fsz) { + inval = 0; + inbits = fsz; + } +} + +/* + * va_start(ap, last) implementation. + * + * f is the NAME node for this builtin function. + * a is the argument list containing: + * CM + * ap last + * + * It turns out that this is easy on MIPS. Just write the + * argument registers to the stack in va_arg_start() and + * use the traditional method of walking the stackframe. + */ +NODE * +mips_builtin_stdarg_start(NODE *f, NODE *a, TWORD t) +{ + NODE *p, *q; + int sz = 1; + + /* check num args and type */ + if (a == NULL || a->n_op != CM || a->n_left->n_op == CM || + !ISPTR(a->n_left->n_type)) + goto bad; + + /* must first deal with argument size; use int size */ + p = a->n_right; + if (p->n_type < INT) { + /* round up to word */ + sz = SZINT / tsize(p->n_type, p->n_df, p->n_ap); + } + + p = buildtree(ADDROF, p, NIL); /* address of last arg */ + p = optim(buildtree(PLUS, p, bcon(sz))); + q = block(NAME, NIL, NIL, PTR+VOID, 0, 0); + q = buildtree(CAST, q, p); + p = q->n_right; + nfree(q->n_left); + nfree(q); + p = buildtree(ASSIGN, a->n_left, p); + tfree(f); + nfree(a); + + return p; + +bad: + uerror("bad argument to __builtin_stdarg_start"); + return bcon(0); +} + +NODE * +mips_builtin_va_arg(NODE *f, NODE *a, TWORD t) +{ + NODE *p, *q, *r; + int sz, tmpnr; + + /* check num args and type */ + if (a == NULL || a->n_op != CM || a->n_left->n_op == CM || + !ISPTR(a->n_left->n_type) || a->n_right->n_op != TYPE) + goto bad; + + r = a->n_right; + + /* get type size */ + sz = tsize(r->n_type, r->n_df, r->n_ap) / SZCHAR; + if (sz < SZINT/SZCHAR) { + werror("%s%s promoted to int when passed through ...", + r->n_type & 1 ? "unsigned " : "", + DEUNSIGN(r->n_type) == SHORT ? "short" : "char"); + sz = SZINT/SZCHAR; + } + + /* alignment */ + p = tcopy(a->n_left); + if (sz > SZINT/SZCHAR && r->n_type != UNIONTY && r->n_type != STRTY) { + p = buildtree(PLUS, p, bcon(7)); + p = block(AND, p, bcon(-8), p->n_type, p->n_df, p->n_ap); + } + + /* create a copy to a temp node */ + q = tempnode(0, p->n_type, p->n_df, p->n_ap); + tmpnr = regno(q); + p = buildtree(ASSIGN, q, p); + + q = tempnode(tmpnr, p->n_type, p->n_df,p->n_ap); + q = buildtree(PLUS, q, bcon(sz)); + q = buildtree(ASSIGN, a->n_left, q); + + q = buildtree(COMOP, p, q); + + nfree(a->n_right); + nfree(a); + nfree(f); + + p = tempnode(tmpnr, INCREF(r->n_type), r->n_df, r->n_ap); + p = buildtree(UMUL, p, NIL); + p = buildtree(COMOP, q, p); + + return p; + +bad: + uerror("bad argument to __builtin_va_arg"); + return bcon(0); +} + +NODE * +mips_builtin_va_end(NODE *f, NODE *a, TWORD t) +{ + tfree(f); + tfree(a); + return bcon(0); +} + +NODE * +mips_builtin_va_copy(NODE *f, NODE *a, TWORD t) +{ + if (a == NULL || a->n_op != CM || a->n_left->n_op == CM) + goto bad; + tfree(f); + f = buildtree(ASSIGN, a->n_left, a->n_right); + nfree(a); + return f; + +bad: + uerror("bad argument to __buildtin_va_copy"); + return bcon(0); +} + +static int constructor; +static int destructor; + +/* + * Give target the opportunity of handling pragmas. + */ +int +mypragma(char *str) +{ + + if (strcmp(str, "tls") == 0) { + uerror("thread-local storage not supported for this target"); + return 1; + } + if (strcmp(str, "constructor") == 0 || strcmp(str, "init") == 0) { + constructor = 1; + return 1; + } + if (strcmp(str, "destructor") == 0 || strcmp(str, "fini") == 0) { + destructor = 1; + return 1; + } + + return 0; +} + +/* + * Called when a identifier has been declared, to give target last word. + */ +void +fixdef(struct symtab *sp) +{ + if ((constructor || destructor) && (sp->sclass != PARAM)) { + printf("\t.section .%ctors,\"aw\",@progbits\n", + constructor ? 'c' : 'd'); + printf("\t.p2align 2\n"); + printf("\t.long %s\n", exname(sp->sname)); + printf("\t.previous\n"); + constructor = destructor = 0; + } +} + +void +pass1_lastchance(struct interpass *ip) +{ +} diff --git a/compilers/pcc/pcc-1.0.0/arch/mips/local2.c b/compilers/pcc/pcc-1.0.0/arch/mips/local2.c new file mode 100644 index 00000000..fe4d3f9b --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/mips/local2.c @@ -0,0 +1,1329 @@ +/* $Id: local2.c,v 1.25 2008/12/03 22:23:38 gmcgarry Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * MIPS port by Jan Enoksson (janeno-1@student.ltu.se) and + * Simon Olsson (simols-1@student.ltu.se) 2005. + */ + +#include +#include +#include +#include + +#include "pass1.h" +#include "pass2.h" + +#ifdef TARGET_BIG_ENDIAN +int bigendian = 1; +#else +int bigendian = 0; +#endif + +int nargregs = MIPS_O32_NARGREGS; + +static int argsiz(NODE *p); + +void +deflab(int label) +{ + printf(LABFMT ":\n", label); +} + +static int regoff[32]; +static TWORD ftype; + +/* + * calculate stack size and offsets + */ +static int +offcalc(struct interpass_prolog * ipp) +{ + int i, j, addto; + + addto = p2maxautooff; + + for (i = ipp->ipp_regs[0], j = 0; i; i >>= 1, j++) { + if (i & 1) { + addto += SZINT / SZCHAR; + regoff[j] = addto; + } + } + + /* round to 8-byte boundary */ + addto += 7; + addto &= ~7; + + return addto; +} + +/* + * Print out the prolog assembler. + */ +void +prologue(struct interpass_prolog * ipp) +{ + int addto; + int i, j; + + ftype = ipp->ipp_type; + printf("\t.align 2\n"); + if (ipp->ipp_vis) + printf("\t.globl %s\n", ipp->ipp_name); + printf("\t.ent %s\n", ipp->ipp_name); + printf("%s:\n", ipp->ipp_name); + + addto = offcalc(ipp); + + /* for the moment, just emit this PIC stuff - NetBSD does it */ + printf("\t.frame %s,%d,%s\n", rnames[FP], ARGINIT/SZCHAR, rnames[RA]); + printf("\t.set noreorder\n"); + printf("\t.cpload $25\t# pseudo-op to load GOT ptr into $25\n"); + printf("\t.set reorder\n"); + + printf("\tsubu %s,%s,%d\n", rnames[SP], rnames[SP], ARGINIT/SZCHAR); + /* for the moment, just emit PIC stuff - NetBSD does it */ + printf("\t.cprestore 8\t# pseudo-op to store GOT ptr at 8(sp)\n"); + + printf("\tsw %s,4(%s)\n", rnames[RA], rnames[SP]); + printf("\tsw %s,(%s)\n", rnames[FP], rnames[SP]); + printf("\tmove %s,%s\n", rnames[FP], rnames[SP]); + +#ifdef notyet + /* profiling */ + if (pflag) { + printf("\t.set noat\n"); + printf("\tmove %s,%s\t# save current return address\n", + rnames[AT], rnames[RA]); + printf("\tsubu %s,%s,8\t# _mcount pops 2 words from stack\n", + rnames[SP], rnames[SP]); + printf("\tjal %s\n", exname("_mcount")); + printf("\tnop\n"); + printf("\t.set at\n"); + } +#endif + + if (addto) + printf("\tsubu %s,%s,%d\n", rnames[SP], rnames[SP], addto); + + for (i = ipp->ipp_regs[0], j = 0; i; i >>= 1, j++) + if (i & 1) + fprintf(stdout, "\tsw %s,-%d(%s) # save permanent\n", + rnames[j], regoff[j], rnames[FP]); + +} + +void +eoftn(struct interpass_prolog * ipp) +{ + int i, j; + int addto; + + addto = offcalc(ipp); + + if (ipp->ipp_ip.ip_lbl == 0) + return; /* no code needs to be generated */ + + /* return from function code */ + for (i = ipp->ipp_regs[0], j = 0; i; i >>= 1, j++) { + if (i & 1) + fprintf(stdout, "\tlw %s,-%d(%s)\n\tnop\n", + rnames[j], regoff[j], rnames[FP]); + } + + printf("\taddiu %s,%s,%d\n", rnames[SP], rnames[FP], ARGINIT/SZCHAR); + printf("\tlw %s,%d(%s)\n", rnames[RA], 4-ARGINIT/SZCHAR, rnames[SP]); + printf("\tlw %s,%d(%s)\n", rnames[FP], 0-ARGINIT/SZCHAR, rnames[SP]); + + printf("\tjr %s\n", rnames[RA]); + printf("\tnop\n"); + +#ifdef USE_GAS + printf("\t.end %s\n", ipp->ipp_name); + printf("\t.size %s,.-%s\n", ipp->ipp_name, ipp->ipp_name); +#endif +} + +/* + * add/sub/... + * + * Param given: + */ +void +hopcode(int f, int o) +{ + char *str; + + switch (o) { + case EQ: + str = "beqz"; /* pseudo-op */ + break; + case NE: + str = "bnez"; /* pseudo-op */ + break; + case ULE: + case LE: + str = "blez"; + break; + case ULT: + case LT: + str = "bltz"; + break; + case UGE: + case GE: + str = "bgez"; + break; + case UGT: + case GT: + str = "bgtz"; + break; + case PLUS: + str = "add"; + break; + case MINUS: + str = "sub"; + break; + case AND: + str = "and"; + break; + case OR: + str = "or"; + break; + case ER: + str = "xor"; + break; + default: + comperr("hopcode2: %d", o); + str = 0; /* XXX gcc */ + } + + printf("%s%c", str, f); +} + +char * +rnames[] = { +#ifdef USE_GAS + /* gnu assembler */ + "$zero", "$at", "$2", "$3", "$4", "$5", "$6", "$7", + "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", + "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", + "$24", "$25", + "$kt0", "$kt1", "$gp", "$sp", "$fp", "$ra", + "$2!!$3!!", + "$4!!$5!!", "$5!!$6!!", "$6!!$7!!", "$7!!$8!!", + "$8!!$9!!", "$9!!$10!", "$10!$11!", "$11!$12!", + "$12!$13!", "$13!$14!", "$14!$15!", "$15!$24!", "$24!$25!", + "$16!$17!", "$17!$18!", "$18!$19!", "$19!$20!", + "$20!$21!", "$21!$22!", "$22!$23!", +#else + /* mips assembler */ + "$zero", "$at", "$v0", "$v1", "$a0", "$a1", "$a2", "$a3", + "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", + "$s0", "$s1", "$s2", "$s3", "$s4", "$s5", "$s6", "$s7", + "$t8", "$t9", + "$k0", "$k1", "$gp", "$sp", "$fp", "$ra", + "$v0!$v1!", + "$a0!$a1!", "$a1!$a2!", "$a2!$a3!", "$a3!$t0!", + "$t0!$t1!", "$t1!$t2!", "$t2!$t3!", "$t3!$t4!", + "$t4!$t5!", "$t5!$t6!", "$t6!$t7!", "$t7!$t8!", "$t8!$t9!", + "$s0!$s1!", "$s1!$s2!", "$s2!$s3!", "$s3!$s4!", + "$s4!$s5!", "$s5!$s6!", "$s6!$s7!", +#endif + "$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", +}; + +char * +rnames_n32[] = { + /* mips assembler */ + "$zero", "$at", "$v0", "$v1", "$a0", "$a1", "$a2", "$a3", + "$a4", "$a5", "$a6", "$a7", "$t0", "$t1", "$t2", "$t3", + "$s0", "$s1", "$s2", "$s3", "$s4", "$s5", "$s6", "$s7", + "$t8", "$t9", + "$k0", "$k1", "$gp", "$sp", "$fp", "$ra", + "$v0!$v1!", + "$a0!$a1!", "$a1!$a2!", "$a2!$a3!", "$a3!$a4!", + "$a4!$a5!", "$a5!$a6!", "$a6!$a7!", "$a7!$t0!", + "$t0!$t1!", "$t1!$t2!", "$t2!$t3!", "$t3!$t8!", "$t8!$t9!", + "$s0!$s1!", "$s1!$s2!", "$s2!$s3!", "$s3!$s4!", + "$s4!$s5!", "$s5!$s6!", "$s6!$s7!", + "$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", +}; + +int +tlen(NODE *p) +{ + switch (p->n_type) { + case CHAR: + case UCHAR: + return (1); + + case SHORT: + case USHORT: + return (SZSHORT / SZCHAR); + + case DOUBLE: + return (SZDOUBLE / SZCHAR); + + case INT: + case UNSIGNED: + case LONG: + case ULONG: + return (SZINT / SZCHAR); + + case LONGLONG: + case ULONGLONG: + return SZLONGLONG / SZCHAR; + + default: + if (!ISPTR(p->n_type)) + comperr("tlen type %d not pointer"); + return SZPOINT(p->n_type) / SZCHAR; + } +} + + +/* + * Push a structure on stack as argument. + */ +static void +starg(NODE *p) +{ + //assert(p->n_rval == A1); + printf("\tsubu %s,%s,%d\n", rnames[SP], rnames[SP], p->n_stsize); + /* A0 = dest, A1 = src, A2 = len */ + printf("\tmove %s,%s\n", rnames[A0], rnames[SP]); + printf("\tli %s,%d\t# structure size\n", rnames[A2], p->n_stsize); + printf("\tsubu %s,%s,16\n", rnames[SP], rnames[SP]); + printf("\tjal %s\t# structure copy\n", exname("memcpy")); + printf("\tnop\n"); + printf("\taddiu %s,%s,16\n", rnames[SP], rnames[SP]); +} + +/* + * Structure assignment. + */ +static void +stasg(NODE *p) +{ + assert(p->n_right->n_rval == A1); + /* A0 = dest, A1 = src, A2 = len */ + printf("\tli %s,%d\t# structure size\n", rnames[A2], p->n_stsize); + if (p->n_left->n_op == OREG) { + printf("\taddiu %s,%s," CONFMT "\t# dest address\n", + rnames[A0], rnames[p->n_left->n_rval], + p->n_left->n_lval); + } else if (p->n_left->n_op == NAME) { + printf("\tla %s,", rnames[A0]); + adrput(stdout, p->n_left); + printf("\n"); + } + printf("\tsubu %s,%s,16\n", rnames[SP], rnames[SP]); + printf("\tjal %s\t# structure copy\n", exname("memcpy")); + printf("\tnop\n"); + printf("\taddiu %s,%s,16\n", rnames[SP], rnames[SP]); +} + +static void +shiftop(NODE *p) +{ + NODE *r = p->n_right; + TWORD ty = p->n_type; + + if (p->n_op == LS && r->n_op == ICON && r->n_lval < 32) { + expand(p, INBREG, "\tsrl A1,AL,"); + printf(CONFMT "\t# 64-bit left-shift\n", 32 - r->n_lval); + expand(p, INBREG, "\tsll U1,UL,AR\n"); + expand(p, INBREG, "\tor U1,U1,A1\n"); + expand(p, INBREG, "\tsll A1,AL,AR\n"); + } else if (p->n_op == LS && r->n_op == ICON && r->n_lval < 64) { + expand(p, INBREG, "\tli A1,0\t# 64-bit left-shift\n"); + expand(p, INBREG, "\tsll U1,AL,"); + printf(CONFMT "\n", r->n_lval - 32); + } else if (p->n_op == LS && r->n_op == ICON) { + expand(p, INBREG, "\tli A1,0\t# 64-bit left-shift\n"); + expand(p, INBREG, "\tli U1,0\n"); + } else if (p->n_op == RS && r->n_op == ICON && r->n_lval < 32) { + expand(p, INBREG, "\tsll U1,UL,"); + printf(CONFMT "\t# 64-bit right-shift\n", 32 - r->n_lval); + expand(p, INBREG, "\tsrl A1,AL,AR\n"); + expand(p, INBREG, "\tor A1,A1,U1\n"); + if (ty == LONGLONG) + expand(p, INBREG, "\tsra U1,UL,AR\n"); + else + expand(p, INBREG, "\tsrl U1,UL,AR\n"); + } else if (p->n_op == RS && r->n_op == ICON && r->n_lval < 64) { + if (ty == LONGLONG) { + expand(p, INBREG, "\tsra U1,UL,31\t# 64-bit right-shift\n"); + expand(p, INBREG, "\tsra A1,UL,"); + }else { + expand(p, INBREG, "\tli U1,0\t# 64-bit right-shift\n"); + expand(p, INBREG, "\tsrl A1,UL,"); + } + printf(CONFMT "\n", r->n_lval - 32); + } else if (p->n_op == LS && r->n_op == ICON) { + expand(p, INBREG, "\tli A1,0\t# 64-bit right-shift\n"); + expand(p, INBREG, "\tli U1,0\n"); + } else { + comperr("shiftop"); + } +} + +/* + * http://gcc.gnu.org/onlinedocs/gccint/Soft-float-library-routines.html#Soft-float-library-routines + */ +static void +fpemulop(NODE *p) +{ + NODE *l = p->n_left; + char *ch = NULL; + + if (p->n_op == PLUS && p->n_type == FLOAT) ch = "addsf3"; + else if (p->n_op == PLUS && p->n_type == DOUBLE) ch = "adddf3"; + else if (p->n_op == PLUS && p->n_type == LDOUBLE) ch = "addtf3"; + + else if (p->n_op == MINUS && p->n_type == FLOAT) ch = "subsf3"; + else if (p->n_op == MINUS && p->n_type == DOUBLE) ch = "subdf3"; + else if (p->n_op == MINUS && p->n_type == LDOUBLE) ch = "subtf3"; + + else if (p->n_op == MUL && p->n_type == FLOAT) ch = "mulsf3"; + else if (p->n_op == MUL && p->n_type == DOUBLE) ch = "muldf3"; + else if (p->n_op == MUL && p->n_type == LDOUBLE) ch = "multf3"; + + else if (p->n_op == DIV && p->n_type == FLOAT) ch = "divsf3"; + else if (p->n_op == DIV && p->n_type == DOUBLE) ch = "divdf3"; + else if (p->n_op == DIV && p->n_type == LDOUBLE) ch = "divtf3"; + + else if (p->n_op == UMINUS && p->n_type == FLOAT) ch = "negsf2"; + else if (p->n_op == UMINUS && p->n_type == DOUBLE) ch = "negdf2"; + else if (p->n_op == UMINUS && p->n_type == LDOUBLE) ch = "negtf2"; + + else if (p->n_op == EQ && l->n_type == FLOAT) ch = "eqsf2"; + else if (p->n_op == EQ && l->n_type == DOUBLE) ch = "eqdf2"; + else if (p->n_op == EQ && l->n_type == LDOUBLE) ch = "eqtf2"; + + else if (p->n_op == NE && l->n_type == FLOAT) ch = "nesf2"; + else if (p->n_op == NE && l->n_type == DOUBLE) ch = "nedf2"; + else if (p->n_op == NE && l->n_type == LDOUBLE) ch = "netf2"; + + else if (p->n_op == GE && l->n_type == FLOAT) ch = "gesf2"; + else if (p->n_op == GE && l->n_type == DOUBLE) ch = "gedf2"; + else if (p->n_op == GE && l->n_type == LDOUBLE) ch = "getf2"; + + else if (p->n_op == LE && l->n_type == FLOAT) ch = "lesf2"; + else if (p->n_op == LE && l->n_type == DOUBLE) ch = "ledf2"; + else if (p->n_op == LE && l->n_type == LDOUBLE) ch = "letf2"; + + else if (p->n_op == GT && l->n_type == FLOAT) ch = "gtsf2"; + else if (p->n_op == GT && l->n_type == DOUBLE) ch = "gtdf2"; + else if (p->n_op == GT && l->n_type == LDOUBLE) ch = "gttf2"; + + else if (p->n_op == LT && l->n_type == FLOAT) ch = "ltsf2"; + else if (p->n_op == LT && l->n_type == DOUBLE) ch = "ltdf2"; + else if (p->n_op == LT && l->n_type == LDOUBLE) ch = "lttf2"; + + else if (p->n_op == SCONV && p->n_type == FLOAT) { + if (l->n_type == DOUBLE) ch = "truncdfsf2"; + else if (l->n_type == LDOUBLE) ch = "trunctfsf2"; + else if (l->n_type == ULONGLONG) ch = "floatdisf"; /**/ + else if (l->n_type == LONGLONG) ch = "floatdisf"; + else if (l->n_type == LONG) ch = "floatsisf"; + else if (l->n_type == ULONG) ch = "floatunsisf"; + else if (l->n_type == INT) ch = "floatsisf"; + else if (l->n_type == UNSIGNED) ch = "floatunsisf"; + } else if (p->n_op == SCONV && p->n_type == DOUBLE) { + if (l->n_type == FLOAT) ch = "extendsfdf2"; + else if (l->n_type == LDOUBLE) ch = "trunctfdf2"; + else if (l->n_type == ULONGLONG) ch = "floatunsdidf"; + else if (l->n_type == LONGLONG) ch = "floatdidf"; + else if (l->n_type == LONG) ch = "floatsidf"; + else if (l->n_type == ULONG) ch = "floatunsidf"; + else if (l->n_type == INT) ch = "floatsidf"; + else if (l->n_type == UNSIGNED) ch = "floatunsidf"; + } else if (p->n_op == SCONV && p->n_type == LDOUBLE) { + if (l->n_type == FLOAT) ch = "extendsftf2"; + else if (l->n_type == DOUBLE) ch = "extenddfdf2"; + else if (l->n_type == ULONGLONG) ch = "floatunsdidf"; + else if (l->n_type == LONGLONG) ch = "floatdidf"; + else if (l->n_type == LONG) ch = "floatsidf"; + else if (l->n_type == ULONG) ch = "floatunssidf"; + else if (l->n_type == INT) ch = "floatsidf"; + else if (l->n_type == UNSIGNED) ch = "floatunsidf"; + } else if (p->n_op == SCONV && p->n_type == ULONGLONG) { + if (l->n_type == FLOAT) ch = "fixunssfdi"; + else if (l->n_type == DOUBLE) ch = "fixunsdfdi"; + else if (l->n_type == LDOUBLE) ch = "fixunsdfdi"; + } else if (p->n_op == SCONV && p->n_type == LONGLONG) { + if (l->n_type == FLOAT) ch = "fixsfdi"; + else if (l->n_type == DOUBLE) ch = "fixdfdi"; + else if (l->n_type == LDOUBLE) ch = "fixdfdi"; + } else if (p->n_op == SCONV && p->n_type == LONG) { + if (l->n_type == FLOAT) ch = "fixsfsi"; + else if (l->n_type == DOUBLE) ch = "fixdfsi"; + else if (l->n_type == LDOUBLE) ch = "fixdfsi"; + } else if (p->n_op == SCONV && p->n_type == ULONG) { + if (l->n_type == FLOAT) ch = "fixunssfsi"; + else if (l->n_type == DOUBLE) ch = "fixunsdfsi"; + else if (l->n_type == LDOUBLE) ch = "fixunsdfsi"; + } else if (p->n_op == SCONV && p->n_type == INT) { + if (l->n_type == FLOAT) ch = "fixsfsi"; + else if (l->n_type == DOUBLE) ch = "fixdfsi"; + else if (l->n_type == LDOUBLE) ch = "fixdfsi"; + } else if (p->n_op == SCONV && p->n_type == UNSIGNED) { + if (l->n_type == FLOAT) ch = "fixunssfsi"; + else if (l->n_type == DOUBLE) ch = "fixunsdfsi"; + else if (l->n_type == LDOUBLE) ch = "fixunsdfsi"; + } + + if (ch == NULL) comperr("ZF: op=0x%x (%d)\n", p->n_op, p->n_op); + + if (p->n_op == SCONV) { + if (l->n_type == FLOAT) { + printf("\tmfc1 %s,", rnames[A0]); + adrput(stdout, l); + printf("\n\tnop\n"); + } else if (l->n_type == DOUBLE || l->n_type == LDOUBLE) { + printf("\tmfc1 %s,", rnames[A1]); + upput(l, 0); + printf("\n\tnop\n"); + printf("\tmfc1 %s,", rnames[A0]); + adrput(stdout, l); + printf("\n\tnop\n"); + } + } else { + comperr("ZF: incomplete softfloat - put args in registers"); + } + + printf("\tjal __%s\t# softfloat operation\n", exname(ch)); + printf("\tnop\n"); + + if (p->n_op >= EQ && p->n_op <= GT) + printf("\tcmp %s,0\n", rnames[V0]); +} + +/* + * http://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html#Integer-library-routines + */ +static void +emulop(NODE *p) +{ + char *ch = NULL; + + if (p->n_op == LS && DEUNSIGN(p->n_type) == LONGLONG) ch = "ashldi3"; + else if (p->n_op == LS && (DEUNSIGN(p->n_type) == LONG || + DEUNSIGN(p->n_type) == INT)) + ch = "ashlsi3"; + + else if (p->n_op == RS && p->n_type == ULONGLONG) ch = "lshrdi3"; + else if (p->n_op == RS && (p->n_type == ULONG || p->n_type == INT)) + ch = "lshrsi3"; + + else if (p->n_op == RS && p->n_type == LONGLONG) ch = "ashrdi3"; + else if (p->n_op == RS && (p->n_type == LONG || p->n_type == INT)) + ch = "ashrsi3"; + + else if (p->n_op == DIV && p->n_type == LONGLONG) ch = "divdi3"; + else if (p->n_op == DIV && (p->n_type == LONG || p->n_type == INT)) + ch = "divsi3"; + + else if (p->n_op == DIV && p->n_type == ULONGLONG) ch = "udivdi3"; + else if (p->n_op == DIV && (p->n_type == ULONG || + p->n_type == UNSIGNED)) + ch = "udivsi3"; + + else if (p->n_op == MOD && p->n_type == LONGLONG) ch = "moddi3"; + else if (p->n_op == MOD && (p->n_type == LONG || p->n_type == INT)) + ch = "modsi3"; + + else if (p->n_op == MOD && p->n_type == ULONGLONG) ch = "umoddi3"; + else if (p->n_op == MOD && (p->n_type == ULONG || + p->n_type == UNSIGNED)) + ch = "umodsi3"; + + else if (p->n_op == MUL && p->n_type == LONGLONG) ch = "muldi3"; + else if (p->n_op == MUL && (p->n_type == LONG || p->n_type == INT)) + ch = "mulsi3"; + + else if (p->n_op == UMINUS && p->n_type == LONGLONG) ch = "negdi2"; + else if (p->n_op == UMINUS && p->n_type == LONG) ch = "negsi2"; + + else ch = 0, comperr("ZE"); + printf("\tsubu %s,%s,16\n", rnames[SP], rnames[SP]); + printf("\tjal __%s\t# emulated operation\n", exname(ch)); + printf("\tnop\n"); + printf("\taddiu %s,%s,16\n", rnames[SP], rnames[SP]); +} + +/* + * Emit code to compare two longlong numbers. + */ +static void +twollcomp(NODE *p) +{ + int o = p->n_op; + int s = getlab2(); + int e = p->n_label; + int cb1, cb2; + + if (o >= ULE) + o -= (ULE-LE); + switch (o) { + case NE: + cb1 = 0; + cb2 = NE; + break; + case EQ: + cb1 = NE; + cb2 = 0; + break; + case LE: + case LT: + cb1 = GT; + cb2 = LT; + break; + case GE: + case GT: + cb1 = LT; + cb2 = GT; + break; + + default: + cb1 = cb2 = 0; /* XXX gcc */ + } + if (p->n_op >= ULE) + cb1 += 4, cb2 += 4; + expand(p, 0, "\tsub A1,UL,UR\t# compare 64-bit values (upper)\n"); + if (cb1) { + printf("\t"); + hopcode(' ', cb1); + expand(p, 0, "A1"); + printf("," LABFMT "\n", s); + printf("\tnop\n"); + } + if (cb2) { + printf("\t"); + hopcode(' ', cb2); + expand(p, 0, "A1"); + printf("," LABFMT "\n", e); + printf("\tnop\n"); + } + expand(p, 0, "\tsub A1,AL,AR\t# (and lower)\n"); + printf("\t"); + hopcode(' ', o); + expand(p, 0, "A1"); + printf("," LABFMT "\n", e); + printf("\tnop\n"); + deflab(s); +} + +static void +fpcmpops(NODE *p) +{ + NODE *l = p->n_left; + + switch (p->n_op) { + case EQ: + if (l->n_type == FLOAT) + expand(p, 0, "\tc.eq.s AL,AR\n"); + else + expand(p, 0, "\tc.eq.d AL,AR\n"); + expand(p, 0, "\tnop\n\tbc1t LC\n"); + break; + case NE: + if (l->n_type == FLOAT) + expand(p, 0, "\tc.eq.s AL,AR\n"); + else + expand(p, 0, "\tc.eq.d AL,AR\n"); + expand(p, 0, "\tnop\n\tbc1f LC\n"); + break; + case LT: + if (l->n_type == FLOAT) + expand(p, 0, "\tc.lt.s AL,AR\n"); + else + expand(p, 0, "\tc.lt.d AL,AR\n"); + expand(p, 0, "\tnop\n\tbc1t LC\n"); + break; + case GE: + if (l->n_type == FLOAT) + expand(p, 0, "\tc.lt.s AL,AR\n"); + else + expand(p, 0, "\tc.lt.d AL,AR\n"); + expand(p, 0, "\tnop\n\tbc1f LC\n"); + break; + case LE: + if (l->n_type == FLOAT) + expand(p, 0, "\tc.le.s AL,AR\n"); + else + expand(p, 0, "\tc.le.d AL,AR\n"); + expand(p, 0, "\tnop\n\tbc1t LC\n"); + break; + case GT: + if (l->n_type == FLOAT) + expand(p, 0, "\tc.le.s AL,AR\n"); + else + expand(p, 0, "\tc.le.d AL,AR\n"); + expand(p, 0, "\tnop\n\tbc1f LC\n"); + break; + } + printf("\tnop\n\tnop\n"); +} + +void +zzzcode(NODE * p, int c) +{ + int sz; + + switch (c) { + + case 'C': /* remove arguments from stack after subroutine call */ + sz = p->n_qual > 16 ? p->n_qual : 16; + printf("\taddiu %s,%s,%d\n", rnames[SP], rnames[SP], sz); + break; + + case 'D': /* long long comparison */ + twollcomp(p); + break; + + case 'E': /* emit emulated ops */ + emulop(p); + break; + + case 'F': /* emit emulate floating point ops */ + fpemulop(p); + break; + + case 'G': /* emit hardware floating-point compare op */ + fpcmpops(p); + break; + + case 'H': /* structure argument */ + starg(p); + break; + + case 'I': /* high part of init constant */ + if (p->n_name[0] != '\0') + comperr("named highword"); + fprintf(stdout, CONFMT, (p->n_lval >> 32) & 0xffffffff); + break; + + case 'O': /* 64-bit left and right shift operators */ + shiftop(p); + break; + + case 'Q': /* emit struct assign */ + stasg(p); + break; + + default: + comperr("zzzcode %c", c); + } +} + +/* ARGSUSED */ +int +rewfld(NODE * p) +{ + return (1); +} + +int +fldexpand(NODE *p, int cookie, char **cp) +{ + CONSZ val; + + if (p->n_op == ASSIGN) + p = p->n_left; + switch (**cp) { + case 'S': + printf("%d", UPKFSZ(p->n_rval)); + break; + case 'H': + printf("%d", UPKFOFF(p->n_rval)); + break; + case 'M': + case 'N': + val = (CONSZ)1 << UPKFSZ(p->n_rval); + --val; + val <<= UPKFOFF(p->n_rval); + printf("0x%llx", (**cp == 'M' ? val : ~val) & 0xffffffff); + break; + default: + comperr("fldexpand"); + } + return 1; +} + +/* + * Does the bitfield shape match? + */ +int +flshape(NODE * p) +{ + int o = p->n_op; + + if (o == OREG || o == REG || o == NAME) + return SRDIR; /* Direct match */ + if (o == UMUL && shumul(p->n_left, SOREG)) + return SROREG; /* Convert into oreg */ + return SRREG; /* put it into a register */ +} + +/* INTEMP shapes must not contain any temporary registers */ +/* XXX should this go away now? */ +int +shtemp(NODE * p) +{ + return 0; +#if 0 + int r; + + if (p->n_op == STARG) + p = p->n_left; + + switch (p->n_op) { + case REG: + return (!istreg(p->n_rval)); + + case OREG: + r = p->n_rval; + if (R2TEST(r)) { + if (istreg(R2UPK1(r))) + return (0); + r = R2UPK2(r); + } + return (!istreg(r)); + + case UMUL: + p = p->n_left; + return (p->n_op != UMUL && shtemp(p)); + } + + if (optype(p->n_op) != LTYPE) + return (0); + return (1); +#endif +} + +void +adrcon(CONSZ val) +{ + printf(CONFMT, val); +} + +void +conput(FILE *fp, NODE *p) +{ + int val = p->n_lval; + + switch (p->n_op) { + case ICON: + if (p->n_name[0] != '\0') { + fprintf(fp, "%s", p->n_name); + if (p->n_lval) + fprintf(fp, "+%d", val); + } else + fprintf(fp, "%d", val); + return; + + default: + comperr("illegal conput"); + } +} + +/* ARGSUSED */ +void +insput(NODE * p) +{ + comperr("insput"); +} + +/* + * Print lower or upper name of 64-bit register. + */ +static void +print_reg64name(FILE *fp, int rval, int hi) +{ + int off = 4 * (hi != 0); + char *regname = rnames[rval]; + + fprintf(fp, "%c%c", + regname[off], + regname[off + 1]); + if (regname[off + 2] != '!') + fputc(regname[off + 2], fp); + if (regname[off + 3] != '!') + fputc(regname[off + 3], fp); +} + +/* + * Write out the upper address, like the upper register of a 2-register + * reference, or the next memory location. + */ +void +upput(NODE * p, int size) +{ + + size /= SZCHAR; + switch (p->n_op) { + case REG: + if (GCLASS(p->n_rval) == CLASSB || GCLASS(p->n_rval) == CLASSC) + print_reg64name(stdout, p->n_rval, 1); + else + fputs(rnames[p->n_rval], stdout); + break; + + case NAME: + case OREG: + p->n_lval += size; + adrput(stdout, p); + p->n_lval -= size; + break; + case ICON: + fprintf(stdout, CONFMT, p->n_lval >> 32); + break; + default: + comperr("upput bad op %d size %d", p->n_op, size); + } +} + +void +adrput(FILE * io, NODE * p) +{ + int r; + /* output an address, with offsets, from p */ + + if (p->n_op == FLD) + p = p->n_left; + + switch (p->n_op) { + + case NAME: + if (p->n_name[0] != '\0') + fputs(p->n_name, io); + if (p->n_lval != 0) + fprintf(io, "+" CONFMT, p->n_lval); + return; + + case OREG: + r = p->n_rval; + + if (p->n_lval) + fprintf(io, "%d", (int) p->n_lval); + + fprintf(io, "(%s)", rnames[p->n_rval]); + return; + case ICON: + /* addressable value of the constant */ + conput(io, p); + return; + + case REG: + if (GCLASS(p->n_rval) == CLASSB || GCLASS(p->n_rval) == CLASSC) + print_reg64name(io, p->n_rval, 0); + else + fputs(rnames[p->n_rval], io); + return; + + default: + comperr("illegal address, op %d, node %p", p->n_op, p); + return; + + } +} + +/* printf conditional and unconditional branches */ +void +cbgen(int o, int lab) +{ +} + +void +myreader(struct interpass * ipole) +{ +} + +#if 0 +/* + * Calculate the stack size for arguments + */ +static int stacksize; + +static void +calcstacksize(NODE *p, void *arg) +{ + int sz; + + printf("op=%d\n", p->n_op); + + if (p->n_op != CALL && p->n_op != STCALL) + return; + + sz = argsiz(p->n_right); + if (sz > stacksize) + stacksize = sz; + +#ifdef PCC_DEBUG + if (x2debug) + printf("stacksize: %d\n", stacksize); +#endif +} +#endif + +/* + * If we're big endian, then all OREG loads of a type + * larger than the destination, must have the + * offset changed to point to the correct bytes in memory. + */ +static void +offchg(NODE *p, void *arg) +{ + NODE *l; + + if (p->n_op != SCONV) + return; + + l = p->n_left; + + if (l->n_op != OREG) + return; + + switch (l->n_type) { + case SHORT: + case USHORT: + if (DEUNSIGN(p->n_type) == CHAR) + l->n_lval += 1; + break; + case LONG: + case ULONG: + case INT: + case UNSIGNED: + if (DEUNSIGN(p->n_type) == CHAR) + l->n_lval += 3; + else if (DEUNSIGN(p->n_type) == SHORT) + l->n_lval += 2; + break; + case LONGLONG: + case ULONGLONG: + if (DEUNSIGN(p->n_type) == CHAR) + l->n_lval += 7; + else if (DEUNSIGN(p->n_type) == SHORT) + l->n_lval += 6; + else if (DEUNSIGN(p->n_type) == INT || + DEUNSIGN(p->n_type) == LONG) + l->n_lval += 4; + break; + default: + comperr("offchg: unknown type"); + break; + } +} + +/* + * Remove some PCONVs after OREGs are created. + */ +static void +pconv2(NODE * p, void *arg) +{ + NODE *q; + + if (p->n_op == PLUS) { + if (p->n_type == (PTR | SHORT) || p->n_type == (PTR | USHORT)) { + if (p->n_right->n_op != ICON) + return; + if (p->n_left->n_op != PCONV) + return; + if (p->n_left->n_left->n_op != OREG) + return; + q = p->n_left->n_left; + nfree(p->n_left); + p->n_left = q; + /* + * This will be converted to another OREG later. + */ + } + } +} + +void +mycanon(NODE * p) +{ + walkf(p, pconv2, 0); +} + +void +myoptim(struct interpass * ipole) +{ + struct interpass *ip; + +#ifdef PCC_DEBUG + if (x2debug) + printf("myoptim:\n"); +#endif + +#if 0 + stacksize = 0; +#endif + + DLIST_FOREACH(ip, ipole, qelem) { + if (ip->type != IP_NODE) + continue; + if (bigendian) + walkf(ip->ip_node, offchg, 0); +#if 0 + walkf(ip->ip_node, calcstacksize, 0); +#endif + } +} + +/* + * Move data between registers. While basic registers aren't a problem, + * we have to handle the special case of overlapping composite registers. + */ +void +rmove(int s, int d, TWORD t) +{ + switch (t) { + case LONGLONG: + case ULONGLONG: + if (s == d+1) { + /* dh = sl, copy low word first */ + printf("\tmove "); + print_reg64name(stdout, d, 0); + printf(","); + print_reg64name(stdout, s, 0); + printf("\t# 64-bit rmove\n"); + printf("\tmove "); + print_reg64name(stdout, d, 1); + printf(","); + print_reg64name(stdout, s, 1); + printf("\n"); + } else { + /* copy high word first */ + printf("\tmove "); + print_reg64name(stdout, d, 1); + printf(","); + print_reg64name(stdout, s, 1); + printf(" # 64-bit rmove\n"); + printf("\tmove "); + print_reg64name(stdout, d, 0); + printf(","); + print_reg64name(stdout, s, 0); + printf("\n"); + } + break; + case FLOAT: + case DOUBLE: + case LDOUBLE: + if (t == FLOAT) + printf("\tmov.s "); + else + printf("\tmov.d "); + print_reg64name(stdout, d, 0); + printf(","); + print_reg64name(stdout, s, 0); + printf("\t# float/double rmove\n"); + break; + default: + printf("\tmove %s,%s\t# default rmove\n", rnames[d], rnames[s]); + } +} + + +/* + * For class c, find worst-case displacement of the number of + * registers in the array r[] indexed by class. + * + * On MIPS, we have: + * + * 32 32-bit registers (8 reserved) + * 26 64-bit pseudo registers (1 unavailable) + * 16 floating-point register pairs + */ +int +COLORMAP(int c, int *r) +{ + int num = 0; + + switch (c) { + case CLASSA: + num += r[CLASSA]; + num += 2*r[CLASSB]; + return num < 24; + case CLASSB: + num += 2*r[CLASSB]; + num += r[CLASSA]; + return num < 25; + case CLASSC: + num += r[CLASSC]; + return num < 6; + } + comperr("COLORMAP"); + return 0; /* XXX gcc */ +} + +/* + * Return a class suitable for a specific type. + */ +int +gclass(TWORD t) +{ + if (t == LONGLONG || t == ULONGLONG) + return CLASSB; + if (t >= FLOAT && t <= LDOUBLE) + return CLASSC; + return CLASSA; +} + +/* + * Calculate argument sizes. + */ +void +lastcall(NODE *p) +{ + int sz; + +#ifdef PCC_DEBUG + if (x2debug) + printf("lastcall:\n"); +#endif + + p->n_qual = 0; + if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL) + return; + + sz = argsiz(p->n_right); + + if ((sz > 4*nargregs) && (sz & 7) != 0) { + printf("\tsubu %s,%s,4\t# align stack\n", + rnames[SP], rnames[SP]); + sz += 4; + assert((sz & 7) == 0); + } + + p->n_qual = sz; /* XXX */ +} + +static int +argsiz(NODE *p) +{ + TWORD t; + int size = 0; + int sz = 0; + + if (p->n_op == CM) { + size = argsiz(p->n_left); + p = p->n_right; + } + + t = p->n_type; + if (t < LONGLONG || t > BTMASK) + sz = 4; + else if (DEUNSIGN(t) == LONGLONG) + sz = 8; + else if (t == DOUBLE || t == LDOUBLE) + sz = 8; + else if (t == FLOAT) + sz = 4; + else if (t == STRTY || t == UNIONTY) + sz = p->n_stsize; + + if (p->n_type == STRTY || p->n_type == UNIONTY) { + return (size + sz); + } + + /* alignment */ + if (sz == 8 && (size & 7) != 0) + sz += 4; + +// printf("size=%d, sz=%d -> %d\n", size, sz, size + sz); + return (size + sz); +} + +/* + * Special shapes. + */ +int +special(NODE *p, int shape) +{ + int o = p->n_op; + switch(shape) { + case SPCON: + if (o == ICON && p->n_name[0] == 0 && + (p->n_lval & ~0xffff) == 0) + return SRDIR; + break; + } + + return SRNOPE; +} + +/* + * Target-dependent command-line options. + */ +void +mflags(char *str) +{ + if (strcasecmp(str, "big-endian") == 0) { + bigendian = 1; + } else if (strcasecmp(str, "little-endian") == 0) { + bigendian = 0; + } else { + fprintf(stderr, "unknown m option '%s'\n", str); + exit(1); + } + +#if 0 + else if (strcasecmp(str, "ips2")) { + } else if (strcasecmp(str, "ips2")) { + } else if (strcasecmp(str, "ips3")) { + } else if (strcasecmp(str, "ips4")) { + } else if (strcasecmp(str, "hard-float")) { + } else if (strcasecmp(str, "soft-float")) { + } else if (strcasecmp(str, "abi=32")) { + nargregs = MIPS_O32_NARGREGS; + } else if (strcasecmp(str, "abi=n32")) { + nargregs = MIPS_N32_NARGREGS; + } else if (strcasecmp(str, "abi=64")) { + nargregs = MIPS_N32_NARGREGS; + } +#endif +} +/* + * Do something target-dependent for xasm arguments. + * Supposed to find target-specific constraints and rewrite them. + */ +int +myxasm(struct interpass *ip, NODE *p) +{ + return 0; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/mips/macdefs.h b/compilers/pcc/pcc-1.0.0/arch/mips/macdefs.h new file mode 100644 index 00000000..08722f25 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/mips/macdefs.h @@ -0,0 +1,350 @@ +/* $Id: macdefs.h,v 1.12 2010/09/21 05:43:59 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * MIPS port by Jan Enoksson (janeno-1@student.ltu.se) and + * Simon Olsson (simols-1@student.ltu.se) 2005. + */ + +/* + * Machine-dependent defines for both passes. + */ + +#if TARGOS == netbsd +#define USE_GAS +#endif + +/* + * Convert (multi-)character constant to integer. + * Assume: If only one value; store at left side (char size), otherwise + * treat it as an integer. + */ +#define makecc(val,i) lastcon = (lastcon<<8)|((val<<24)>>24); + +#define ARGINIT (16*8) /* # bits above fp where arguments start */ +#define AUTOINIT (0) /* # bits below fp where automatics start */ + +/* + * Storage space requirements + */ +#define SZCHAR 8 +#define SZBOOL 32 +#define SZINT 32 +#define SZFLOAT 32 +#define SZDOUBLE 64 +#define SZLDOUBLE 64 +#define SZLONG 32 +#define SZSHORT 16 +#define SZLONGLONG 64 +#define SZPOINT(t) 32 + +/* + * Alignment constraints + */ +#define ALCHAR 8 +#define ALBOOL 32 +#define ALINT 32 +#define ALFLOAT 32 +#define ALDOUBLE 64 +#define ALLDOUBLE 64 +#define ALLONG 32 +#define ALLONGLONG 64 +#define ALSHORT 16 +#define ALPOINT 32 +#define ALSTRUCT 64 +#define ALSTACK 32 + +/* + * Min/max values. + */ +#define MIN_CHAR -128 +#define MAX_CHAR 127 +#define MAX_UCHAR 255 +#define MIN_SHORT -32768 +#define MAX_SHORT 32767 +#define MAX_USHORT 65535 +#define MIN_INT -1 +#define MAX_INT 0x7fffffff +#define MAX_UNSIGNED 0xffffffff +#define MIN_LONG MIN_INT +#define MAX_LONG MAX_INT +#define MAX_ULONG MAX_UNSIGNED +#define MIN_LONGLONG 0x8000000000000000LL +#define MAX_LONGLONG 0x7fffffffffffffffLL +#define MAX_ULONGLONG 0xffffffffffffffffULL + +#undef CHAR_UNSIGNED +#define BOOL_TYPE INT + +/* + * Use large-enough types. + */ +typedef long long CONSZ; +typedef unsigned long long U_CONSZ; +typedef long long OFFSZ; + +#define CONFMT "%lld" /* format for printing constants */ +#ifdef USE_GAS +#define LABFMT "$L%d" /* format for printing labels */ +#define STABLBL "$LL%d" /* format for stab (debugging) labels */ +#else +#define LABFMT "L%d" /* format for printing labels */ +#define STABLBL "LL%d" /* format for stab (debugging) labels */ +#endif + +#define BACKAUTO /* stack grows negatively for automatics */ +#define BACKTEMP /* stack grows negatively for temporaries */ + +#undef FIELDOPS /* no bit-field instructions */ +#define RTOLBYTES 1 /* bytes are numbered right to left */ + +#define ENUMSIZE(high,low) INT /* enums are always stored in full int */ + +/* Definitions mostly used in pass2 */ + +#define BYTEOFF(x) ((x)&03) +#define BITOOR(x) (x) /* bit offset to oreg offset */ + +#define szty(t) (((t) == DOUBLE || (t) == LDOUBLE || \ + DEUNSIGN(t) == LONGLONG) ? 2 : 1) + +/* + * Register names. These must match rnames[] and rstatus[] in local2.c. + */ +#define ZERO 0 +#define AT 1 +#define V0 2 +#define V1 3 +#define A0 4 +#define A1 5 +#define A2 6 +#define A3 7 +#define A4 8 +#define A5 9 +#define A6 10 +#define A7 11 +#if defined(MIPS_N32) || defined(MIPS_N64) +#define T0 12 +#define T1 13 +#define T2 14 +#define T3 15 +#else +#define T0 8 +#define T1 9 +#define T2 10 +#define T3 11 +#endif +#define T4 12 +#define T5 13 +#define T6 14 +#define T7 15 +#define S0 16 +#define S1 17 +#define S2 18 +#define S3 19 +#define S4 20 +#define S5 21 +#define S6 22 +#define S7 23 +#define T8 24 +#define T9 25 +#define K0 26 +#define K1 27 +#define GP 28 +#define SP 29 +#define FP 30 +#define RA 31 + +#define V0V1 32 +#define A0A1 33 +#define A1A2 34 +#define A2A3 35 + +/* we just use o32 naming here, but it works ok for n32/n64 */ +#define A3T0 36 +#define T0T1 37 +#define T1T2 38 +#define T2T3 39 +#define T3T4 40 +#define T4T5 41 +#define T5T6 42 +#define T6T7 43 +#define T7T8 44 + +#define T8T9 45 +#define S0S1 46 +#define S1S2 47 +#define S2S3 48 +#define S3S4 49 +#define S4S5 50 +#define S5S6 51 +#define S6S7 52 + +#define F0 53 +#define F2 54 +#define F4 55 +#define F6 56 +#define F8 57 +#define F10 58 +#define F12 59 +#define F14 60 +#define F16 61 +#define F18 62 +#define F20 63 +/* and the rest for later */ +#define F22 64 +#define F24 65 +#define F26 66 +#define F28 67 +#define F30 68 + +#define MAXREGS 64 +#define NUMCLASS 3 + +#define RETREG(x) (DEUNSIGN(x) == LONGLONG ? V0V1 : \ + (x) == DOUBLE || (x) == LDOUBLE || (x) == FLOAT ? \ + F0 : V0) +#define FPREG FP /* frame pointer */ + +#define MIPS_N32_NARGREGS 8 +#define MIPS_O32_NARGREGS 4 + +#define RSTATUS \ + 0, 0, \ + SAREG|TEMPREG, SAREG|TEMPREG, \ + SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \ + SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \ + SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \ + SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, \ + SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, \ + SAREG|TEMPREG, SAREG|TEMPREG, \ + 0, 0, \ + 0, 0, 0, 0, \ + \ + SBREG|TEMPREG, \ + SBREG|TEMPREG, SBREG|TEMPREG, SBREG|TEMPREG, \ + SBREG|TEMPREG, \ + SBREG|TEMPREG, SBREG|TEMPREG, SBREG|TEMPREG, \ + SBREG|TEMPREG, SBREG|TEMPREG, \ + SBREG|TEMPREG, SBREG|TEMPREG, SBREG|TEMPREG, SBREG|TEMPREG, \ + SBREG, SBREG, SBREG, SBREG, \ + SBREG, SBREG, SBREG, \ + SCREG, SCREG, SCREG, SCREG, \ + SCREG, SCREG, SCREG, SCREG, \ + SCREG, SCREG, SCREG, \ + +#define ROVERLAP \ + { -1 }, /* $zero */ \ + { -1 }, /* $at */ \ + { V0V1, -1 }, /* $v0 */ \ + { V0V1, -1 }, /* $v1 */ \ + { A0A1, -1 }, /* $a0 */ \ + { A0A1, A1A2, -1 }, /* $a1 */ \ + { A1A2, A2A3, -1 }, /* $a2 */ \ + { A2A3, A3T0, -1 }, /* $a3 */ \ + { A3T0, T0T1, -1 }, /* $t0 */ \ + { T0T1, T1T2, -1 }, /* $t1 */ \ + { T1T2, T2T3, -1 }, /* $t2 */ \ + { T2T3, T3T4, -1 }, /* $t3 */ \ + { T3T4, T4T5, -1 }, /* $t4 */ \ + { T4T5, T5T6, -1 }, /* $t5 */ \ + { T6T7, T7T8, -1 }, /* $t6 */ \ + { T7T8, T8T9, -1 }, /* $t7 */ \ + \ + { S0S1, -1 }, /* $s0 */ \ + { S0S1, S1S2, -1 }, /* $s1 */ \ + { S1S2, S2S3, -1 }, /* $s2 */ \ + { S2S3, S3S4, -1 }, /* $s3 */ \ + { S3S4, S4S5, -1 }, /* $s4 */ \ + { S4S5, S5S6, -1 }, /* $s5 */ \ + { S5S6, S6S7, -1 }, /* $s6 */ \ + { S6S7, -1 }, /* $s7 */ \ + \ + { T7T8, T8T9, -1 }, /* $t8 */ \ + { T8T9, -1 }, /* $t9 */ \ + \ + { -1 }, /* $k0 */ \ + { -1 }, /* $k1 */ \ + { -1 }, /* $gp */ \ + { -1 }, /* $sp */ \ + { -1 }, /* $fp */ \ + { -1 }, /* $ra */ \ + \ + { V0, V1, -1 }, /* $v0:$v1 */ \ + \ + { A0, A1, A1A2, -1 }, /* $a0:$a1 */ \ + { A1, A2, A0A1, A2A3, -1 }, /* $a1:$a2 */ \ + { A2, A3, A1A2, A3T0, -1 }, /* $a2:$a3 */ \ + { A3, T0, A2A3, T0T1, -1 }, /* $a3:$t0 */ \ + { T0, T1, A3T0, T1T2, -1 }, /* $t0:$t1 */ \ + { T1, T2, T0T1, T2T3, -1 }, /* $t1:$t2 */ \ + { T2, T3, T1T2, T3T4, -1 }, /* $t2:$t3 */ \ + { T3, T4, T2T3, T4T5, -1 }, /* $t3:$t4 */ \ + { T4, T5, T3T4, T5T6, -1 }, /* $t4:$t5 */ \ + { T5, T6, T4T5, T6T7, -1 }, /* $t5:$t6 */ \ + { T6, T7, T5T6, T7T8, -1 }, /* $t6:$t7 */ \ + { T7, T8, T6T7, T8T9, -1 }, /* $t7:$t8 */ \ + { T8, T9, T7T8, -1 }, /* $t8:$t9 */ \ + \ + { S0, S1, S1S2, -1 }, /* $s0:$s1 */ \ + { S1, S2, S0S1, S2S3, -1 }, \ + { S2, S3, S1S2, S3S4, -1 }, \ + { S3, S4, S2S3, S4S5, -1 }, \ + { S4, S5, S3S4, S5S6, -1 }, \ + { S5, S6, S4S5, S6S7, -1 }, \ + { S6, S7, S5S6, -1 }, \ + \ + { -1 }, { -1 }, { -1 }, { -1 }, \ + { -1 }, { -1 }, { -1 }, { -1 }, \ + { -1 }, { -1 }, { -1 }, \ + +#define GCLASS(x) (x < 32 ? CLASSA : (x < 52 ? CLASSB : CLASSC)) +#define PCLASS(p) (1 << gclass((p)->n_type)) +#define DECRA(x,y) (((x) >> (y*6)) & 63) /* decode encoded regs */ +#define ENCRA(x,y) ((x) << (6+y*6)) /* encode regs in int */ +#define ENCRD(x) (x) /* Encode dest reg in n_reg */ + +int COLORMAP(int c, int *r); + +extern int bigendian; +extern int nargregs; + +#define SPCON (MAXSPECIAL+1) /* positive constant */ + +#define TARGET_STDARGS +#define TARGET_BUILTINS \ + { "__builtin_stdarg_start", mips_builtin_stdarg_start, 2 }, \ + { "__builtin_va_arg", mips_builtin_va_arg, 2 }, \ + { "__builtin_va_end", mips_builtin_va_end, 1 }, \ + { "__builtin_va_copy", mips_builtin_va_copy, 2 }, + +struct node; +struct node *mips_builtin_stdarg_start(struct node *f, struct node *a, unsigned int); +struct node *mips_builtin_va_arg(struct node *f, struct node *a, unsigned int); +struct node *mips_builtin_va_end(struct node *f, struct node *a, unsigned int); +struct node *mips_builtin_va_copy(struct node *f, struct node *a, unsigned int); diff --git a/compilers/pcc/pcc-1.0.0/arch/mips/order.c b/compilers/pcc/pcc-1.0.0/arch/mips/order.c new file mode 100644 index 00000000..24f63512 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/mips/order.c @@ -0,0 +1,259 @@ +/* $Id: order.c,v 1.12 2008/11/30 21:00:24 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * MIPS port by Jan Enoksson (janeno-1@student.ltu.se) and + * Simon Olsson (simols-1@student.ltu.se) 2005. + */ + +#include "pass2.h" + +/* + * is it legal to make an OREG or NAME entry which has an offset of off, + * (from a register of r), if the resulting thing had type t + */ +int +notoff(TWORD t, int r, CONSZ off, char *cp) +{ + /* + * although the hardware doesn't permit offsets greater + * than +/- 32K, the assembler fixes it for us. + */ + return 0; /* YES */ +} + +/* + * Turn a UMUL-referenced node into OREG. + */ +void +offstar(NODE * p, int shape) +{ + if (x2debug) + printf("offstar(%p)\n", p); + + if (p->n_op == PLUS || p->n_op == MINUS) { + if (p->n_right->n_op == ICON) { + if (isreg(p->n_left) == 0) + (void)geninsn(p->n_left, INAREG); + /* Converted in ormake() */ + return; + } + } + (void)geninsn(p, INAREG); +} + +/* + * Do the actual conversion of offstar-found OREGs into real OREGs. + */ +void +myormake(NODE * q) +{ + if (x2debug) + printf("myormake(%p)\n", q); +} + +/* + * Shape matches for UMUL. Cooperates with offstar(). + */ +int +shumul(NODE *p, int shape) +{ + if (x2debug) + printf("shumul(%p)\n", p); + + /* Always turn it into OREG */ + if (shape & SOREG) + return SROREG; + return SRNOPE; +} + +/* + * Rewrite operations on binary operators (like +, -, etc...). + * Called as a result of table lookup. + */ +int +setbin(NODE * p) +{ + + if (x2debug) + printf("setbin(%p)\n", p); + return 0; + +} + +/* setup for assignment operator */ +int +setasg(NODE * p, int cookie) +{ + if (x2debug) + printf("setasg(%p)\n", p); + return (0); +} + +/* setup for unary operator */ +int +setuni(NODE * p, int cookie) +{ + return 0; +} + +/* + * Special handling of some instruction register allocation. + * - left is the register that left node wants. + * - right is the register that right node wants. + * - res is in which register the result will end up. + * - mask is registers that will be clobbered. + */ +struct rspecial * +nspecial(struct optab * q) +{ + switch (q->op) { + + case SCONV: + if (q->lshape == SBREG && q->rshape == SCREG) { + static struct rspecial s[] = { + { NLEFT, A0A1 }, + { NRES, F0 }, + { 0 } + }; + return s; + } else if (q->lshape == SCREG && q->rshape == SBREG) { + static struct rspecial s[] = { + { NLEFT, F0 }, + { NRES, A0A1 }, + { 0 } + }; + return s; + } else if (q->lshape == SAREG && q->rshape == SCREG) { + static struct rspecial s[] = { + { NLEFT, A0 }, + { NRES, F0 }, + { 0 } + }; + return s; + } + break; + + case MOD: + case DIV: + if (q->lshape == SBREG) { + static struct rspecial s[] = { + { NLEFT, A0A1 }, + { NRIGHT, A2A3 }, + { NRES, V0V1 }, + { 0 }, + }; + return s; + } else if (q->lshape == SAREG) { + static struct rspecial s[] = { + { NLEFT, A0 }, + { NRIGHT, A1 }, + { NRES, V0 }, + { 0 }, + }; + return s; + } + + case RS: + case LS: + if (q->lshape == SBREG) { + static struct rspecial s[] = { + { NLEFT, A0A1 }, + { NRIGHT, A2 }, + { NRES, V0V1 }, + { 0 }, + }; + return s; + } else if (q->lshape == SAREG) { + static struct rspecial s[] = { + { NLEFT, A0 }, + { NRIGHT, A1 }, + { NRES, V0 }, + { 0 }, + }; + return s; + } + break; + + case STARG: + { + static struct rspecial s[] = { + { NEVER, A0 }, + { NLEFT, A1 }, + { NEVER, A2 }, + { 0 } + }; + return s; + } + + case STASG: + { + static struct rspecial s[] = { + { NEVER, A0 }, + { NRIGHT, A1 }, + { NEVER, A2 }, + { 0 } + }; + return s; + } + } + + comperr("nspecial entry %d: %s", q - table, q->cstring); + + return 0; /* XXX gcc */ +} + +/* + * Set evaluation order of a binary node if it differs from default. + */ +int +setorder(NODE * p) +{ + return 0; /* nothing differs */ +} + +/* + * Set registers "live" at function calls (like arguments in registers). + * This is for liveness analysis of registers. + */ +int * +livecall(NODE *p) +{ + static int r[1] = { -1 }; /* Terminate with -1 */ + + return &r[0]; +} + +/* + * Signal whether the instruction is acceptable for this target. + */ +int +acceptable(struct optab *op) +{ + return 1; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/mips/table.c b/compilers/pcc/pcc-1.0.0/arch/mips/table.c new file mode 100644 index 00000000..f70de8fd --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/mips/table.c @@ -0,0 +1,1580 @@ +/* $Id: table.c,v 1.14 2010/09/19 13:54:41 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * MIPS port by Jan Enoksson (janeno-1@student.ltu.se) and + * Simon Olsson (simols-1@student.ltu.se) 2005. + * + * It appears that the target machine was big endian. The original + * code contained many endian aspects which are now handled in + * machine-independent code. + * + * On MIPS, the assembler does an amazing amount of work for us. + * We don't have to worry about PIC, nor about finding the address + * of SNAMES. Whenever possible, we defer the work to the assembler. + */ + +#include "pass2.h" + +#define TUWORD TUNSIGNED|TULONG +#define TSWORD TINT|TLONG +#define TWORD TUWORD|TSWORD + +struct optab table[] = { +/* First entry must be an empty entry */ +{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", }, + +/* PCONVs are usually not necessary */ +{ PCONV, INAREG, + SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + 0, RLEFT, + " # convert between word and pointer", }, + +/* + * Conversions of integral<->integral types + */ + +{ SCONV, INAREG, + SOREG, TCHAR, + SAREG, TSWORD|TSHORT, + NAREG, RESC1, + " lb A1,AL # convert oreg char to short/int\n" + " nop\n", }, + +{ SCONV, INAREG, + SOREG, TCHAR, + SAREG, TUWORD|TUSHORT|TUCHAR, + NAREG, RESC1, + " lbu A1,AL # convert oreg char to uchar/ushort/uint\n" + " nop\n", }, + +{ SCONV, INAREG, + SOREG, TUCHAR, + SAREG, TWORD|TSHORT|TUSHORT, + NAREG, RESC1, + " lbu A1,AL # convert oreg uchar to (u)short/(u)int\n" + " nop\n", }, + +{ SCONV, INBREG, + SOREG, TCHAR, + SBREG, TLONGLONG, + NBREG, RESC1, + " lb A1,AL # convert oreg char to longlong\n" + " nop\n" + " sra U1,A1,31\n", }, + +/* chor -> ulonglong handled later */ + +{ SCONV, INBREG, + SOREG, TUCHAR, + SBREG, TLONGLONG|TULONGLONG, + NBREG, RESC1, + " lbu A1,AL # convert oreg uchar to (u)longlong\n" + " move U1,$zero\n", }, + +{ SCONV, INAREG, + SOREG, TSHORT|TUSHORT, + SAREG, TCHAR, + NAREG, RESC1, + " lb A1,AL # convert oreg (u)short to char (endianness problem?)\n" + " nop\n", }, + +{ SCONV, INAREG, + SOREG, TSHORT|TUSHORT, + SAREG, TUCHAR, + NAREG, RESC1, + " lbu A1,AL # convert oreg (u)short to uchar (endianness problem?)\n" + " nop\n", }, + +{ SCONV, INAREG, + SOREG, TSHORT, + SAREG, TSWORD, + NAREG, RESC1, + " lh A1,AL # convert oreg short to int\n" + " nop\n", }, + +{ SCONV, INAREG, + SOREG, TSHORT, + SAREG, TUWORD, + NAREG, RESC1, + " lhu A1,AL # convert oreg short to uint\n" + " nop\n", }, + +{ SCONV, INAREG, + SOREG, TUSHORT, + SAREG, TWORD, + NAREG, RESC1, + " lhu A1,AL # convert oreg ushort to (u)int\n" + " nop\n", }, + +{ SCONV, INBREG, + SOREG, TSHORT, + SBREG, TLONGLONG, + NBREG, RESC1, + " lh A1,AL # convert oreg short to longlong\n" + " nop\n" + " sra U1,A1,31\n", }, + +{ SCONV, INBREG, + SOREG, TSHORT, + SBREG, TULONGLONG, + NBREG, RESC1, + " lhu A1,AL # convert oreg short to ulonglong\n" + " nop\n" + " move U1,$zero\n", }, + +{ SCONV, INBREG, + SOREG, TUSHORT, + SBREG, TLONGLONG|TULONGLONG, + NBREG, RESC1, + " lhu A1,AL # convert oreg ushort to (u)longlong\n" + " move U1,$zero\n", }, + +{ SCONV, INAREG, + SOREG, TWORD, + SAREG, TCHAR, + NAREG, RESC1, + " lb A1,AL # convert oreg word to char (endianness problem here?)\n" + " nop\n", }, + +{ SCONV, INAREG, + SOREG, TWORD, + SAREG, TUCHAR, + NAREG, RESC1, + " lbu A1,AL # convert oreg word to uchar (endianness problem here?)\n" + " nop\n", }, + +{ SCONV, INAREG, + SOREG, TWORD, + SAREG, TSHORT, + NAREG, RESC1, + " lh A1,AL # convert oreg word to short (endianness problem here?)\n" + " nop\n", }, + +/* convert (u)long to ushort */ +{ SCONV, INAREG, + SOREG, TWORD, + SAREG, TUSHORT, + NAREG, RESC1, + " lhu A1,AL # convert oreg word to ushort (endianness problem here?)\n" + " nop\n", }, + +{ SCONV, INBREG, + SOREG, TSWORD, + SBREG, TLONGLONG|TULONGLONG, + NBREG, RESC1, + " lw A1,AL # convert oreg int/long to (u)llong (endianness problem here?)\n" + " nop\n" + " sra U1,A1,31\n" }, + +{ SCONV, INBREG, + SOREG, TUWORD, + SBREG, TLONGLONG|TULONGLONG, + NBREG, RESC1, + " lw A1,AL # convert oreg (u)int to (u)llong (endianness problem here?)\n" + " move U1,$zero\n", }, + +{ SCONV, INAREG, + SOREG, TLONGLONG|TULONGLONG, + SAREG, TCHAR, + NAREG, RESC1, + " lb A1,AL # convert oreg (u)llong to char (endianness problem here?)\n" + " nop\n", }, + +{ SCONV, INAREG, + SOREG, TLONGLONG|TULONGLONG, + SAREG, TUCHAR, + NAREG, RESC1, + " lbu A1,AL # convert oreg (u)llong to uchar (endianness problem?)\n" + " nop\n", }, + +{ SCONV, INAREG, + SOREG, TLONGLONG|TULONGLONG, + SAREG, TSHORT, + NAREG, RESC1, + " lh A1,AL # convert oreg (u)llong to short (endianness problem?)\n" + " nop\n", }, + +{ SCONV, INAREG, + SOREG, TLONGLONG|TULONGLONG, + SAREG, TUSHORT, + NAREG, RESC1, + " lhu A1,AL # convert oreg (u)llong to ushort (endianness problem here?)\n" + " nop\n", }, + +{ SCONV, INAREG, + SOREG, TLONGLONG|TULONGLONG, + SAREG, TWORD, + NAREG, RESC1, + " lw A1,AL # convert oreg (u)llong to (u)int (endianness problem here?)\n" + " nop\n", }, + +/* + * Conversions of integral types (register-register) + * + * For each deunsigned type, they look something like this: + * + * signed -> bigger signed - nothing to do + * signed -> bigger unsigned - clear the top bits (of source type) + * + * signed -> smaller signed - sign-extend the bits (to dest type) + * signed -> smaller unsigned - clear the top bits (of dest type) + * unsigned -> smaller signed - sign-extend top bits (to dest type) + * unsigned -> smaller unsigned - clear the top bits (of dest type) + * + * unsigned -> bigger - nothing to do + */ + +{ SCONV, INAREG, + SAREG, TPOINT|TWORD, + SAREG, TPOINT|TWORD, + 0, RLEFT, + " # convert int to int\n", }, + +{ SCONV, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + 0, RLEFT, + " # convert (u)longlong to (u)longlong", }, + +{ SCONV, INAREG, + SAREG, TCHAR, + SAREG, TSWORD|TSHORT, + 0, RLEFT, + " # convert char to short/int\n", }, + +{ SCONV, INAREG, + SAREG, TCHAR, + SAREG, TUWORD|TUSHORT|TUCHAR, + NAREG|NASL, RESC1, + " andi A1,AL,255 # convert char to uchar/ushort/uint\n", }, + +{ SCONV, INAREG, + SAREG, TUCHAR, + SAREG, TCHAR, + NAREG|NASL, RESC1, + " sll A1,AL,24 # convert uchar to char\n" + " sra A1,A1,24\n", }, + +{ SCONV, INAREG, + SAREG, TUCHAR, + SAREG, TWORD|TSHORT|TUSHORT, + 0, RLEFT, + " # convert uchar to (u)short/(u)int\n", }, + +{ SCONV, INAREG, + SAREG, TSHORT, + SAREG, TCHAR, + NAREG|NASL, RESC1, + " sll A1,AL,24 # convert short to char\n" + " sra A1,A1,24\n", }, + +{ SCONV, INAREG, + SAREG, TSHORT, + SAREG, TUCHAR, + NAREG|NASL, RESC1, + " andi A1,AL,255 # convert short to uchar\n", }, + +{ SCONV, INAREG, + SAREG, TSHORT, + SAREG, TUWORD|TUSHORT, + NAREG|NASL, RESC1, + " andi A1,AL,65535 # convert short to ushort\n", }, + +{ SCONV, INAREG, + SAREG, TSHORT, + SAREG, TSWORD, + NAREG|NASL, RESC1, + " sll A1,AL,16 # convert short to ushort\n" + " sra A1,A1,16\n", }, + +{ SCONV, INAREG, + SAREG, TUSHORT, + SAREG, TCHAR, + NAREG|NASL, RESC1, + " sll A1,AL,24 # convert short to char\n" + " sra A1,A1,24\n", }, + +{ SCONV, INAREG, + SAREG, TUSHORT, + SAREG, TUCHAR, + NAREG|NASL, RESC1, + " andi A1,AL,255 # convert ushort to char\n", }, + +{ SCONV, INAREG, + SAREG, TUSHORT, + SAREG, TSHORT, + NAREG|NASL, RESC1, + " sll A1,AL,16 # convert short to ushort\n" + " sra A1,A1,16\n", }, + +{ SCONV, INAREG, + SAREG, TUSHORT, + SAREG, TWORD, + 0, RDEST, + " # convert ushort to (u)int\n", }, + +{ SCONV, INAREG, + SAREG, TSWORD, + SAREG, TCHAR, + NAREG|NASL, RESC1, + " sll A1,AL,8 # convert int to char\n" + " sra A1,A1,8\n", }, + +{ SCONV, INAREG, + SAREG, TSWORD, + SAREG, TUCHAR, + NAREG|NASL, RESC1, + " andi A1,AL,255 # convert int to uchar\n", }, + +{ SCONV, INAREG, + SAREG, TSWORD, + SAREG, TSHORT, + NAREG|NASL, RESC1, + " sll A1,AL,16 # convert int to short\n" + " sra A1,A1,16\n", }, + +{ SCONV, INAREG, + SAREG, TSWORD, + SAREG, TUSHORT, + NAREG|NASL, RESC1, + " andi A1,AL,65535 # convert int to ushort\n", }, + +{ SCONV, INAREG, + SAREG, TUWORD, + SAREG, TCHAR, + NAREG|NASL, RESC1, + " sll A1,AL,24 # convert int to char\n" + " sra A1,A1,24\n", }, + +{ SCONV, INAREG, + SAREG, TUWORD, + SAREG, TUCHAR, + NAREG|NASL, RESC1, + " andi A1,AL,255 # convert int to uchar\n", }, + +{ SCONV, INAREG, + SAREG, TUWORD, + SAREG, TSHORT, + NAREG|NASL, RESC1, + " sll A1,AL,16 # convert int to short\n" + " sra A1,A1,16\n", }, + +{ SCONV, INAREG, + SAREG, TUWORD, + SAREG, TUSHORT, + NAREG|NASL, RESC1, + " andi A1,AL,65535 # convert int to ushort\n", }, + +{ SCONV, INBREG, + SAREG, TSWORD|TSHORT|TCHAR, + SBREG, TLONGLONG, + NBREG, RESC1, + " move A1,AL # convert int/short/char to longlong\n" + " sra U1,AL,31\n", }, + +{ SCONV, INBREG, + SAREG, TSWORD|TSHORT|TCHAR, + SBREG, TULONGLONG, + NBREG, RESC1, + " move A1,AL # convert int/short/char to ulonglong\n" + " move U1,$zero\n", }, + +{ SCONV, INBREG, + SAREG, TWORD|TUSHORT|TSHORT|TUCHAR|TCHAR, + SBREG, TLONGLONG|TULONGLONG, + NBREG, RESC1, + " move A1,AL # convert (u)int/(u)short/(u)char to ulonglong\n" + " move U1,$zero\n", }, + +{ SCONV, INAREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TWORD, + NAREG, RESC1, + " move A1,AL # convert (u)longlong to int\n", }, + +{ SCONV, INAREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TSHORT, + NAREG, RESC1, + " sll A1,AL,16 # convert (u)longlong to short\n" + " sra A1,A1,16\n", }, + +{ SCONV, INAREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TCHAR, + NAREG, RESC1, + " sll A1,AL,24 # convert (u)longlong to char\n" + " sra A1,A1,24\n", }, + +{ SCONV, INAREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TUSHORT, + NAREG, RESC1, + " andi A1,AL,65535 # convert (u)longlong to ushort\n", }, + +{ SCONV, INAREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TUCHAR, + NAREG, RESC1, + " andi A1,AL,255 # convert (u)longlong to uchar\n", }, + +{ SCONV, INCREG, + SCREG, TFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + NCREG, RESC1, + " cvt.d.s A1,AL # convert float to (l)double\n", }, + +{ SCONV, INCREG, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TFLOAT, + NCREG, RESC1, + " cvt.s.d A1,AL # convert (l)double to float\n", }, + +{ SCONV, INCREG, + SAREG, TWORD, + SCREG, TFLOAT, + NCREG, RESC1, + " mtc1 AL,A1 # convert (u)int to float\n" + " nop\n" + " cvt.s.w A1,A1\n", }, + +{ SCONV, INCREG, + SOREG, TWORD, + SCREG, TFLOAT, + NCREG, RESC1, + " l.s A1,AL # convert (u)int to float\n" + " nop\n" + " cvt.s.w A1,A1\n", }, + +{ SCONV, INCREG, + SAREG, TWORD, + SCREG, TDOUBLE|TLDOUBLE, + NCREG, RESC1, + " mtc1 AL,A1 # convert (u)int to (l)double\n" + " nop\n" + " cvt.d.w A1,A1\n", }, + +{ SCONV, INCREG, + SOREG, TWORD, + SCREG, TDOUBLE|TLDOUBLE, + NCREG, RESC1, + " l.d A1,AL # convert (u)int to (l)double\n" + " nop\n" + " cvt.d.w A1,A1\n", }, + +{ SCONV, INAREG, + SCREG, TFLOAT, + SAREG, TWORD, + NCREG|NAREG, RESC1, + " cvt.w.s A2,AL # convert float to (u)int\n" + " mfc1 A1,A2\n" + " nop\n", }, + +{ SCONV, FOREFF, + SCREG, TFLOAT, + SOREG, TWORD, + NCREG, RDEST, + " cvt.w.s A1,AL # convert float to (u)int\n" + " s.s A1,AR\n" + " nop\n", }, + +{ SCONV, INAREG, + SCREG, TDOUBLE|TLDOUBLE, + SAREG, TWORD, + NCREG|NAREG, RESC1, + " cvt.w.d A2,AL # convert (l)double to (u)int\n" + " mfc1 A1,A2\n" + " nop\n", }, + +{ SCONV, INCREG, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + 0, RLEFT, + " # convert between double and ldouble\n", }, + +{ SCONV, INCREG, + SBREG, TLONGLONG|TULONGLONG, + SCREG, TFLOAT, + NSPECIAL|NCREG, RESC1, + "ZF", }, + +{ SCONV, INCREG, + SBREG, TLONGLONG|TULONGLONG, + SCREG, TDOUBLE|TLDOUBLE, + NSPECIAL|NCREG, RESC1, + "ZF", }, + +{ SCONV, INBREG, + SCREG, TDOUBLE|TLDOUBLE, + SBREG, TLONGLONG|TULONGLONG, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +{ SCONV, INBREG, + SCREG, TFLOAT, + SBREG, TLONGLONG|TULONGLONG, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +/* + * Multiplication and division + */ + +{ MUL, INAREG, + SAREG, TUWORD|TUSHORT|TUCHAR, + SAREG, TUWORD|TUSHORT|TUCHAR, + NAREG|NASR|NASL, RESC1, + " multu AL,AR # unsigned multiply\n" + " mflo A1\n" + " nop\n" + " nop\n", }, + +/* this previous will match on unsigned/unsigned multiplication first */ +{ MUL, INAREG, + SAREG, TWORD|TUSHORT|TSHORT|TUCHAR|TCHAR, + SAREG, TWORD|TUSHORT|TSHORT|TUCHAR|TCHAR, + NAREG|NASR|NASL, RESC1, + " mult AL,AR # signed multiply\n" + " mflo A1\n" + " nop\n" + " nop\n", }, + +{ MUL, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + 2*NBREG, RESC1, + " multu AL,AR\n" + " mfhi U1\n" + " mflo A1\n" + " mult AL,UR\n" + " mflo A2\n" + " nop\n" + " nop\n" + " addu A2,U1,A2\n" + " mult UL,AR\n" + " mflo U2\n" + " nop\n" + " nop\n" + " addu U1,A2,U2\n", }, + +{ MUL, INCREG, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, + " mul.s A1,AL,AR # floating-point multiply\n", }, + +{ MUL, INCREG, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + NCREG, RESC1, + " mul.d A1,AL,AR # double-floating-point multiply\n", }, + +{ DIV, INAREG, + SAREG, TUWORD|TUSHORT|TUCHAR, + SAREG, TUWORD|TUSHORT|TUCHAR, + NAREG|NASR|NASL, RESC1, + " divu AL,AR # unsigned division\n" + " mflo A1\n" + " nop\n" + " nop\n", }, + +/* the previous rule will match unsigned/unsigned first */ +{ DIV, INAREG, + SAREG, TWORD|TUSHORT|TSHORT|TUCHAR|TCHAR, + SAREG, TWORD|TUSHORT|TSHORT|TUCHAR|TCHAR, + NAREG|NASR|NASL, RESC1, + " div AL,AR # signed division\n" + " mflo A1\n" + " nop\n" + " nop\n", }, + +{ DIV, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NSPECIAL|NBREG, RESC1, + "ZE", }, + +{ DIV, INCREG, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, + " div.s A1,AL,AR # floating-point division\n", }, + +{ DIV, INCREG, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + NCREG, RESC1, + " div.d A1,AL,AR # double-floating-point division\n", }, + +{ MOD, INAREG, + SAREG, TUWORD|TUSHORT|TUCHAR, + SAREG, TUWORD|TUSHORT|TUCHAR, + NAREG, RESC1, + " divu AL,AR # signed modulo\n" + " mfhi A1\n" + " nop\n" + " nop\n", }, + +/* the previous rule will match unsigned%unsigned first */ +{ MOD, INAREG, + SAREG, TWORD|TUSHORT|TSHORT|TUCHAR|TCHAR, + SAREG, TWORD|TUSHORT|TSHORT|TUCHAR|TCHAR, + NAREG, RESC1, + " div AL,AR # signed modulo\n" + " mfhi A1\n" + " nop\n" + " nop\n", }, + +{ MOD, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NSPECIAL|NBREG, RESC1, + "ZE", }, + +/* + * Templates for unsigned values needs to come before OPSIMP + */ + +{ PLUS, INBREG, + SBREG, TULONGLONG|TLONGLONG, + SBREG, TULONGLONG|TLONGLONG, + 2*NBREG, RESC1, + " addu A1,AL,AR # 64-bit addition\n" + " sltu A2,A1,AR\n" + " addu U1,UL,UR\n" + " addu U1,U1,A2\n", }, + +{ PLUS, INAREG, + SAREG, TSWORD|TSHORT|TCHAR, + SSCON, TANY, + NAREG|NASL, RESC1, + " addi A1,AL,AR\n", }, + +{ PLUS, INAREG, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + SSCON, TANY, + NAREG|NASL, RESC1, + " addiu A1,AL,AR\n", }, + +{ PLUS, INAREG, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + SAREG, TUWORD|TUSHORT|TUCHAR, + NAREG|NASL, RESC1, + " addu A1,AL,AR\n", }, + +{ PLUS, INAREG, + SAREG, TSWORD|TSHORT|TCHAR, + SAREG, TSWORD|TSHORT|TCHAR, + NAREG|NASL, RESC1, + " add A1,AL,AR\n", }, + +{ PLUS, INCREG, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG|NCSL, RESC1, + " add.s A1,AL,AR\n", }, + +{ PLUS, INCREG, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + NCREG|NCSL, RESC1, + " add.d A1,AL,AR\n", }, + +{ MINUS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + 2*NBREG, RESC1, + " sltu A2,AL,AR # 64-bit subtraction\n" + " subu A1,AL,AR\n" + " subu U1,UL,UR\n" + " subu U1,U1,A2\n", }, + +{ MINUS, INAREG, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + SSCON, TANY, + NAREG|NASL, RESC1, + " subu A1,AL,AR\n", }, + +{ MINUS, INAREG, + SAREG, TSWORD|TSHORT|TCHAR, + SSCON, TANY, + NAREG|NASL, RESC1, + " sub A1,AL,AR\n", }, + +{ MINUS, INAREG, + SAREG, TSWORD|TSHORT|TCHAR, + SAREG, TSWORD|TSHORT|TCHAR, + NAREG|NASL, RESC1, + " sub A1,AL,AR\n", }, + +{ MINUS, INCREG, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG|NCSL, RESC1, + " sub.s A1,AL,AR\n", }, + +{ MINUS, INCREG, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + NCREG|NCSL, RESC1, + " sub.d A1,AL,AR\n", }, + +{ UMINUS, INAREG, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SANY, TANY, + NAREG|NASL, RESC1, + " neg A1,AL\n", }, + +{ UMINUS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SANY, TANY, + NBREG|NAREG|NBSL, RESC2, + " subu A1,$zero,AL\n" + " subu U1,$zero,UL\n" + " sltu A2,$zero,A1\n" + " subu U1,U1,A2\n", }, + +{ UMINUS, INCREG, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG|NCSL, RESC1, + " neg.s A1,AL\n", }, + +{ UMINUS, INCREG, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + NCREG|NCSL, RESC1, + " neg.d A1,AL\n", }, + +/* Simple 'op rd, rs, rt' or 'op rt, rs, imm' operations */ + +{ OPSIMP, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NBREG|NBSR|NBSL, RESC1, + " O A1,AL,AR\n" + " O U1,UL,UR\n", }, + +{ OPSIMP, INAREG, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TUCHAR|TCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TUCHAR|TCHAR, + NAREG|NASR|NASL, RESC1, + " O A1,AL,AR\n", }, + +{ OPSIMP, INAREG, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TUCHAR|TCHAR, + SPCON, TANY, + NAREG|NASL, RESC1, + " Oi A1,AL,AR\n", }, + +/* + * Shift instructions + */ + +{ RS, INAREG, + SAREG, TSWORD|TSHORT|TCHAR, + SCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " sra A1,AL,AR # shift right by constant\n", }, + +{ RS, INAREG, + SAREG, TUWORD|TUSHORT|TUCHAR, + SCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " srl A1,AL,AR # shift right by constant\n", }, + +{ LS, INAREG, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " sll A1,AL,AR # shift left by constant\n", }, + +{ RS, INAREG, + SAREG, TSWORD|TSHORT|TCHAR, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " srav A1,AL,AR # shift right by register\n", }, + +{ RS, INAREG, + SAREG, TUWORD|TUSHORT|TUCHAR, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " srlv A1,AL,AR # shift right by register\n", }, + +{ LS, INAREG, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " sllv A1,AL,AR # shift left by register\n", }, + +{ RS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NBREG, RESC1, + "ZO", }, + +{ LS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NBREG, RESC1, + "ZO", }, + +{ RS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NSPECIAL|NBREG, RESC1, + "ZE", }, + +{ LS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NSPECIAL|NBREG, RESC1, + "ZE", }, + +/* + * Rule for unary one's complement + */ + +{ COMPL, INAREG, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SANY, TANY, + NAREG|NASL, RESC1, + " nor A1,$zero,AL # complement\n", }, + +{ COMPL, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SANY, TANY, + NBREG|NBSL, RESC1, + " nor A1,$zero,AL # complement\n" + " nor U1,$zero,UL\n", }, + +/* + * The next rules takes care of assignments. "=". + */ + +{ ASSIGN, FOREFF|INAREG, + SOREG|SNAME, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + 0, RDEST, + " sw AR,AL # store (u)int/(u)long\n" + " nop\n", }, + +{ ASSIGN, FOREFF|INAREG, + SOREG|SNAME, TSHORT|TUSHORT, + SAREG, TSHORT|TUSHORT, + 0, RDEST, + " sh AR,AL # store (u)short\n" + " nop\n", }, + +{ ASSIGN, FOREFF|INAREG, + SOREG|SNAME, TCHAR|TUCHAR, + SAREG, TCHAR|TUCHAR, + 0, RDEST, + " sb AR,AL # store (u)char\n" + " nop\n", }, + +{ ASSIGN, FOREFF|INBREG, + SOREG|SNAME, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + 0, RDEST, + " sw UR,UL # store (u)longlong\n" + " nop\n" + " sw AR,AL\n" + " nop\n", }, + +{ ASSIGN, FOREFF|INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + 0, RDEST, + " move UL,UR # register move\n" + " move AL,AR\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TANY, + SAREG, TANY, + 0, RDEST, + " move AL,AR # register move\n", }, + +{ ASSIGN, FOREFF|INCREG, + SCREG, TFLOAT, + SCREG, TFLOAT, + 0, RDEST, + " mov.s AL,AR # register move\n", }, + +{ ASSIGN, FOREFF|INCREG, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + 0, RDEST, + " mov.d AL,AR # register move\n", }, + +{ ASSIGN, FOREFF|INCREG, + SNAME|SOREG, TFLOAT, + SCREG, TFLOAT, + 0, RDEST, + " s.s AR,AL # store floating-point reg to oreg/sname\n" + " nop\n", }, + +{ ASSIGN, FOREFF|INCREG, + SNAME|SOREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + 0, RDEST, + " s.d AR,AL # store double floating-point reg to oreg/sname\n" + " nop\n", }, + +{ ASSIGN, FOREFF|INAREG, + SFLD, TANY, + SOREG|SNAME, TANY, + 3*NAREG, RDEST, + " lw A1,AR # bit-field assignment\n" + " li A3,M\n" + " lw A2,AL\n" + " sll A1,A1,H\n" + " and A1,A1,A3\n" + " nor A3,$zero,A3\n" + " and A2,A2,A3\n" + " or A2,A2,A1\n" + " sw A2,AL\n" + "F lw AD,AR\n" + "F nop\n" + "F sll AD,AD,32-S\n" + "F sra AD,AD,32-S\n", }, + +/* XXX we can optimise this away */ +{ ASSIGN, FOREFF|INAREG, + SFLD, TANY, + SCON, TANY, + 3*NAREG, RDEST, + " li A1,AR # bit-field assignment\n" + " lw A2,AL\n" + " li A3,M\n" + " sll A1,A1,H\n" + " and A1,A1,A3\n" + " nor A3,$zero,A3\n" + " and A2,A2,A3\n" + " or A2,A2,A1\n" + " sw A2,AL\n" + "F li AD,AR\n" + "F sll AD,AD,32-S\n" + "F sra AD,AD,32-S\n", }, + +{ ASSIGN, FOREFF|INAREG, + SFLD, TANY, + SAREG, TANY, + 3*NAREG, RDEST, + " move A1,AR # bit-field assignment\n" + " lw A2,AL\n" + " li A3,M\n" + " sll A1,A1,H\n" + " and A1,A1,A3\n" + " nor A3,$zero,A3\n" + " and A2,A2,A3\n" + " or A2,A2,A1\n" + " sw A2,AL\n" + "F move AR,AD\n" + "F sll AD,AD,32-S\n" + "F sra AD,AD,32-S\n", }, + +{ STASG, INAREG|FOREFF, + SOREG|SNAME, TANY, + SAREG, TPTRTO|TANY, + NSPECIAL, RDEST, + "ZQ", }, + +/* + * Compare instructions + */ + +{ EQ, FORCC, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + 0, RESCC, + " beq AL,AR,LC\n" + " nop\n", }, + +{ NE, FORCC, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + 0, RESCC, + " bne AL,AR,LC\n" + " nop\n", }, + +{ OPLOG, FORCC, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SZERO, TANY, + 0, RESCC, + " O AL,LC\n" + " nop\n", }, + +{ OPLOG, FORCC, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESCC, + " sub A1,AL,AR\n" + " O A1,LC\n" + " nop\n", }, + +{ OPLOG, FORCC, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SSCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESCC, + " sub A1,AL,AR\n" + " O A1,LC\n" + " nop\n", }, + +{ OPLOG, FORCC, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NAREG, RESCC, + "ZD", }, + +{ OPLOG, FORCC, + SCREG, TFLOAT|TDOUBLE|TLDOUBLE, + SCREG, TFLOAT|TDOUBLE|TLDOUBLE, + 0, RESCC, + "ZG", }, + +/* + * Convert LTYPE to reg. + */ + +{ OPLTYPE, INAREG, + SANY, TANY, + SOREG|SNAME, TCHAR, + NAREG, RESC1, + " lb A1,AL # load char to reg\n" + " nop\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SOREG|SNAME, TUCHAR, + NAREG, RESC1, + " lbu A1,AL # load uchar to reg\n" + " nop\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SOREG|SNAME, TSHORT, + NAREG, RESC1, + " lh A1,AL # load short to reg\n" + " nop\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SOREG|SNAME, TUSHORT, + NAREG, RESC1, + " lhu A1,AL # load ushort to reg\n" + " nop\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SOREG|SNAME, TWORD|TPOINT, + NAREG, RESC1, + " lw A1,AL # load (u)int/(u)long to reg\n" + " nop\n", }, + +{ OPLTYPE, INBREG, + SANY, TANY, + SOREG|SNAME, TLONGLONG|TULONGLONG, + NBREG, RESC1, + " lw U1,UL # load (u)longlong to reg\n" + " nop\n" + " lw A1,AL\n" + " nop\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SCON, TPOINT, + NAREG, RESC1, + " la A1,AL # load constant address to reg\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SZERO, TANY, + NAREG, RESC1, + " move A1,$zero # load 0 to reg\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SCON, TANY, + NAREG, RESC1, + " li A1,AL # load constant to reg\n", }, + +{ OPLTYPE, INBREG, + SANY, TANY, + SZERO, TANY, + NBREG, RESC1, + " move A1,$zero # load 0 to reg\n" + " move U1,$zero\n", }, + +{ OPLTYPE, INBREG, + SANY, TANY, + SCON, TANY, + NBREG, RESC1, + " li A1,AL # load constant to reg\n" + " li U1,UL\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SANY, TANY, + NAREG, RESC1, + " move A1,AL\n", }, + +{ OPLTYPE, INCREG, + SANY, TANY, + SZERO, TFLOAT, + NCREG, RESC1, + " mtc1 $zero,A1 # load 0 to float reg\n" + " nop\n", }, + +{ OPLTYPE, INCREG, + SANY, TANY, + SZERO, TDOUBLE|TLDOUBLE, + NCREG, RESC1, + " mtc1 $zero,A1 # load 0 to (l)double reg\n" + " mtc1 $zero,U1\n" + " nop\n", }, + +{ OPLTYPE, INCREG, + SANY, TANY, + SOREG|SNAME, TFLOAT, + NCREG, RESC1, + " l.s A1,AL # load into floating-point reg\n" + " nop\n", }, + +{ OPLTYPE, INCREG, + SANY, TANY, + OREG|SNAME, TDOUBLE|TLDOUBLE, + NCREG, RESC1, + " l.d A1,AL # load into double floating-point reg\n" + " nop\n", }, + +/* + * Jumps. + */ +{ GOTO, FOREFF, + SCON, TANY, + SANY, TANY, + 0, RNOP, + " j LL # goto label\n" + " nop\n" + " nop\n", }, + +/* + * Subroutine calls. + */ + +{ CALL, FOREFF, + SCON, TANY, + SANY, TANY, + 0, 0, + " subu $sp,$sp,16 # call (args, no result) to scon/sname\n" + " jal CL\n" + " nop\n" + "ZC", }, + +{ UCALL, FOREFF, + SCON, TANY, + SANY, TANY, + 0, 0, + " jal CL # call (no args, no result) to scon/sname\n" + " nop\n", }, + +{ CALL, INAREG, + SCON, TANY, + SAREG, TANY, + NAREG, RESC1, /* should be 0 */ + " subu $sp,$sp,16 # call (args, result in v0) to scon/sname\n" + " jal CL\n" + " nop\n" + "ZC", }, + +{ UCALL, INAREG, + SCON, TANY, + SAREG, TANY, + NAREG, RESC1, /* should be 0 */ + " jal CL # call (no args, result in v0) to scon/sname\n" + " nop\n", + }, + +{ CALL, INBREG, + SCON, TANY, + SBREG, TANY, + NBREG, RESC1, /* should be 0 */ + " subu $sp,$sp,16 # call (args, result in v0:v1) to scon/sname\n" + " jal CL\n" + " nop\n" + "ZC", }, + +{ UCALL, INBREG, + SCON, TANY, + SBREG, TANY, + NBREG, RESC1, /* should be 0 */ + " jal CL # call (no args, result in v0:v1) to scon/sname\n" + " nop\n", + }, + +{ CALL, INCREG, + SCON, TANY, + SCREG, TANY, + NCREG, RESC1, /* should be 0 */ + " subu $sp,$sp,16 # call (args, result in f0:f1) to scon/sname\n" + " jal CL\n" + " nop\n" + "ZC", }, + +{ UCALL, INCREG, + SCON, TANY, + SCREG, TANY, + NCREG, RESC1, /* should be 0 */ + " jal CL # call (no args, result in v0:v1) to scon/sname\n" + " nop\n", + }, + +{ CALL, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, 0, + " subu $sp,$sp,16 # call (args, no result) to reg\n" + " move $25,AL\n" + " jal $25\n" + " nop\n" + "ZC", }, + +{ UCALL, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, 0, + " move $25,AL\n" + " jal $25 # call (no args, no result) to reg\n" + " nop\n", }, + +{ CALL, INAREG, + SAREG, TANY, + SAREG, TANY, + NAREG, RESC1, /* should be 0 */ + " subu $sp,$sp,16 # call (args, result) to reg\n" + " move $25,AL\n" + " jal $25\n" + " nop\n" + "ZC", }, + +{ UCALL, INAREG, + SAREG, TANY, + SAREG, TANY, + NAREG, RESC1, /* should be 0 */ + " move $25,AL\n" + " jal $25 # call (no args, result) to reg\n" + " nop\n", }, + +{ CALL, INBREG, + SAREG, TANY, + SBREG, TANY, + NBREG, RESC1, /* should be 0 */ + " subu $sp,$sp,16 # call (args, result) to reg\n" + " move $25,AL\n" + " jal $25\n" + " nop\n" + "ZC", }, + +{ UCALL, INBREG, + SAREG, TANY, + SBREG, TANY, + NBREG, RESC1, /* should be 0 */ + " move $25,AL\n" + " jal $25 # call (no args, result) to reg\n" + " nop\n", }, + +{ CALL, INCREG, + SAREG, TANY, + SCREG, TANY, + NCREG, RESC1, /* should be 0 */ + " subu $sp,$sp,16 # call (args, result) to reg\n" + " move $25,AL\n" + " jal $25\n" + " nop\n" + "ZC", }, + +{ UCALL, INCREG, + SCREG, TANY, + SCREG, TANY, + NCREG, RESC1, /* should be 0 */ + " move $25,AL\n" + " jal $25 # call (no args, result) to reg\n" + " nop\n", }, + + +/* struct return */ +{ USTCALL, FOREFF, + SCON|SNAME, TANY, + SANY, TANY, + 0, 0, + " jal CL\n" + " nop\n", }, + +{ USTCALL, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, 0, + " move $25,AL\n" + " jal $25\n" + " nop\n", }, + +{ USTCALL, INAREG, + SCON|SNAME, TANY, + SANY, TANY, + NAREG|NASL, RESC1, + " jal CL\n" + " nop\n", }, + +{ USTCALL, INAREG, + SAREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1, + " move $25,AL\n" + " jal $25\n" + " nop\n", }, + +{ STCALL, FOREFF, + SCON|SNAME, TANY, + SANY, TANY, + 0, 0, + " subu $sp,$sp,16\n" + " jal CL\n" + " nop\n" + "ZC", }, + +{ STCALL, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, 0, + " subu $sp,$sp,16\n" + " move $25,AL\n" + " jal $25\n" + " nop\n" + "ZC", }, + +{ STCALL, INAREG, + SCON|SNAME, TANY, + SANY, TANY, + NAREG|NASL, RESC1, + " subu $sp,$sp,16\n" + " jal CL\n" + " nop\n" + "ZC", }, + +{ STCALL, INAREG, + SAREG, TANY, + SANY, TANY, + 0, 0, + " subu $sp,$sp,16\n" + " move $25,AL\n" + " jal $25\n" + " nop\n" + "ZC", }, + + +/* + * Function arguments + */ + +#if 0 + +/* intentionally write out the register for (u)short/(u)char */ +{ FUNARG, FOREFF, + SAREG, TWORD|TPOINT|TUSHORT|TSHORT|TUCHAR|TCHAR, + SANY, TWORD|TPOINT|TUSHORT|TSHORT|TUCHAR|TCHAR, + 0, 0, + " subu $sp,$sp,4 # save function arg to stack\n" + " sw AL,($sp)\n" + " #nop\n", }, + +{ FUNARG, FOREFF, + SBREG, TLONGLONG|TULONGLONG, + SANY, TLONGLONG|TULONGLONG, + 0, 0, + " addi $sp,$sp,-8 # save function arg to stack (endian problem here?\n" + " sw UL,4($sp)\n" + " sw AL,($sp)\n" + " #nop\n", }, + +{ FUNARG, FOREFF, + SCREG, TFLOAT, + SANY, TFLOAT, + 0, 0, + " addi $sp,$sp,-4 # save function arg to stack\n" + " s.s AL,($sp)\n" + " #nop\n", }, + +{ FUNARG, FOREFF, + SCREG, TDOUBLE|TLDOUBLE, + SANY, TDOUBLE|TLDOUBLE, + 0, 0, + " addi $sp,$sp,-8 # save function arg to stack\n" + " s.d AL,($sp)\n" + " #nop\n", }, + +#endif + +{ STARG, FOREFF, + SAREG, TANY, + SANY, TSTRUCT, + NSPECIAL, 0, + "ZH", }, + +/* + * Indirection operators. + */ +{ UMUL, INAREG, + SANY, TPOINT|TWORD, + SOREG, TPOINT|TWORD, + NAREG, RESC1, + " lw A1,AL # word load\n" + " nop\n", }, + +{ UMUL, INAREG, + SANY, TSHORT|TUSHORT, + SOREG, TSHORT|TUSHORT, + NAREG, RESC1, + " lh A1,AL # (u)short load\n" + " nop\n", }, + +{ UMUL, INAREG, + SANY, TCHAR|TUCHAR, + SOREG, TCHAR|TUCHAR, + NAREG, RESC1, + " lb A1,AL # (u)char load\n" + " nop\n", }, + +{ UMUL, INBREG, + SANY, TLONGLONG|TULONGLONG, + SOREG, TLONGLONG|TULONGLONG, + NBREG, RESC1, + " lw A1,AL # (u)longlong load - endian problem here?\n" + " nop\n" + " lw U1,UL\n" + " nop\n", }, + +{ UMUL, INCREG, + SANY, TFLOAT, + SOREG, TFLOAT, + NCREG, RESC1, + " l.s A1,AL # float load\n" + " nop\n", }, + +{ UMUL, INCREG, + SANY, TDOUBLE|TLDOUBLE, + SOREG, TDOUBLE|TLDOUBLE, + NCREG, RESC1, + " l.d A1,AL # float load\n" + " nop\n", }, + +#if 0 +{ UMUL, INCREG, + SANY, TDOUBLE|TLDOUBLE, + SAREG, TPOINT, + NCREG, RESC1, + " l.d A1,(AL)\n" + " nop\n", }, + +{ UMUL, INAREG, + SANY, TPOINT|TWORD, + SNAME, TPOINT|TWORD, + NAREG, RESC1, + " la A1,AL # sname word load\n" + " lw A1,(A1)\n" + " nop\n", }, + +{ UMUL, INAREG, + SANY, TSHORT|TUSHORT, + SNAME, TSHORT|TUSHORT, + NAREG, RESC1, + " la A1,AL # sname (u)short load\n" + " lh A1,(A1)\n" + " nop\n", }, + +{ UMUL, INAREG, + SANY, TCHAR|TUCHAR, + SNAME, TCHAR|TUCHAR, + NAREG, RESC1, + " la A1,AL # sname (u)char load\n" + " lb A1,(A1)\n" + " nop\n", }, + +{ UMUL, INBREG, + SANY, TLONGLONG|TULONGLONG, + SNAME, TLONGLONG|TULONGLONG, + NBREG|NAREG, RESC1, + " la A2,AL # sname (u)long long load - endian problems here?\n" + " lw A1,(A1)\n" + " nop\n" + " lw U1,4(A1)\n" + " nop\n", }, +#endif + +{ UMUL, INAREG, + SANY, TPOINT|TWORD, + SAREG, TPOINT|TWORD, + NAREG, RESC1, + " lw A1,(AL) # word load\n" + " nop\n", }, + +#if 0 +{ UMUL, INAREG, + SANY, TSHORT|TUSHORT, + SAREG, TPTRTO|TSHORT|TUSHORT, + NAREG, RESC1, + " lh A1,(AL) # (u)short load\n" + " nop\n", }, + +{ UMUL, INAREG, + SANY, TCHAR|TUCHAR, + SAREG, TPTRTO|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " lb A1,(AL) # (u)char load\n" + " nop\n", }, + +{ UMUL, INBREG, + SANY, TLONGLONG|TULONGLONG, + SAREG, TPTRTO|TLONGLONG|TULONGLONG, + NBREG, RESC1, + " lw A1,(AL) # (u)long long load - endianness problems?\n" + " nop\n" + " lw U1,4(AL)" + " nop\n", }, +#endif + +#define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,"" + +{ FLD, DF(FLD), }, + +{ FREE, FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" }, +}; + +int tablesize = sizeof(table)/sizeof(table[0]); diff --git a/compilers/pcc/pcc-1.0.0/arch/nova/CVS/Entries b/compilers/pcc/pcc-1.0.0/arch/nova/CVS/Entries new file mode 100644 index 00000000..7f426f5b --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/nova/CVS/Entries @@ -0,0 +1,8 @@ +/README/1.2/Thu Sep 28 11:13:21 2006//Tr-1-0-0-RELEASE +/code.c/1.5/Tue Jan 1 17:31:00 2008//Tr-1-0-0-RELEASE +/local.c/1.8/Fri Jan 21 21:47:58 2011//Tr-1-0-0-RELEASE +/local2.c/1.7/Sat Nov 1 08:29:37 2008//Tr-1-0-0-RELEASE +/macdefs.h/1.2/Fri Nov 16 22:27:42 2007//Tr-1-0-0-RELEASE +/order.c/1.4/Sat Sep 27 07:35:23 2008//Tr-1-0-0-RELEASE +/table.c/1.1/Sun Jul 30 09:30:48 2006//Tr-1-0-0-RELEASE +D diff --git a/compilers/pcc/pcc-1.0.0/arch/nova/CVS/Repository b/compilers/pcc/pcc-1.0.0/arch/nova/CVS/Repository new file mode 100644 index 00000000..00c31575 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/nova/CVS/Repository @@ -0,0 +1 @@ +pcc/arch/nova diff --git a/compilers/pcc/pcc-1.0.0/arch/nova/CVS/Root b/compilers/pcc/pcc-1.0.0/arch/nova/CVS/Root new file mode 100644 index 00000000..71e2ccb9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/nova/CVS/Root @@ -0,0 +1 @@ +/cvsroot diff --git a/compilers/pcc/pcc-1.0.0/arch/nova/CVS/Tag b/compilers/pcc/pcc-1.0.0/arch/nova/CVS/Tag new file mode 100644 index 00000000..060fac05 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/nova/CVS/Tag @@ -0,0 +1 @@ +Nr-1-0-0-RELEASE diff --git a/compilers/pcc/pcc-1.0.0/arch/nova/README b/compilers/pcc/pcc-1.0.0/arch/nova/README new file mode 100644 index 00000000..939f8061 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/nova/README @@ -0,0 +1,120 @@ +Calling conventions, stack frame and zero page: + +The variables that normally are placed on the stack or in registers in C +are instead allocated in the zero page and saved on a (fictive) stack +when calling functions. Some locations have predefined functions though. +Arrays allocated as automatics are stored on the stack with a pointer +in zero page to its destination. + +0-7 Unused +10 Stack pointer +11 Frame pointer +12-14 Unused +15 Used by prolog +16 Prolog address, written in crt0 +17 Epilog address, written in crt0 +20-27 Auto-increment, scratch +30-37 Auto-decrement, scratch +40-47 Unused +50-57 Scratch/Arguments +60-77 Permanent, save before use. +100-377 Addresses for subroutines, written by the assembler + +The normal registers (AC0-AC3) are all considered scratch registers. + +Register classes are assigned as: + AC0-AC3: AREGs. + AC2-AC3: BREGs. + 50-77: CREGs. + ...and eventually register pairs as DREGs. + +In byte code the low half of a word is the first byte (little-endian). +This is bit 8-15 in Nova syntax. + +The stack is growing towards lower adresses (as opposed to the Eclipse stack). +Stack layout: + + ! arg1 ! + ! arg0 ! + fp -> ! old pc! + ! old fp! + pc -> ! saved ! + +A reference to a struct member in assembler, a = b->c; b is in ZP 50 ++ is zeropage-addressing +* is fp-adressing + +# offset 0 ++ lda 0,@50 # load value from indirect ZP 50 into ac0 +* lda 2,,3 # load value from (ac3) into ac2 +* lda 0,,2 # load value from (ac2) into ac0 + +# offset 12 ++ lda 2,50 # load value from ZP 50 into ac2 ++ lda 0,12,2 # load value from (ac2+12) into ac0 +* lda 2,,3 # load value from (ac3) into ac2 +* lda 0,12,2 # load value from 12(ac2) into ac0 + +# offset 517 ++ lda 2,50 # load value from ZP 50 into ac2 ++ lda 0,.L42-.,1 # load offset from .L42 PC-indexed ++ addz 0,2,skp # add offset to ac2 and skip ++.L42: .word 517 # offset value ++ lda 0,,2 # load value from (ac2) into ac0 + +The prolog/epilog implementation; it is implemented as subroutines. + +.L42: .word 13 # number of words to save +func: + sta 3,@40 # save return address on stack + lda 2,.L42-.,1 # get save word count + jsr @45 # go to prolog + ... + lda 2,.L42-.,1 # get restore word count + jmp @46 # jump to epilog + +# words to save in 2, return address in 3 +prolog: + sta 2,45 # save # of words to move at scratch + lda 0,41 # get old fp + lda 1,40 # get sp + sta 1,41 # save new fp + dsz 40 # decrement stack, will never be 0 + sta 0,@40 # save old fp + dsz 40 + + lda 0,off57 # fetch address of regs to save - 1 + sta 0,20 # store address at autoincr +1: lda 0,@20 # get word to copy + sta 0,@40 # push on stack + dsz 40 # manually decrement sp + dsz 45 # copied all words? + jmp 1b,1 # no, continue + jmp 0,3 # return + +epilog: + sta 2,45 # save # of words to move at scratch + + lda 3,off57 # fetch address of regs to save + sta 3,20 # store at autoincr + lda 3,41 # fetch fp + sta 3,30 # store at autodecr + lda 3,@30 # get old fp + +1: lda 2,@30 # fetch word from stack + sta 2,@20 # store at orig place + dsz 45 # enough? + jmp 1b,1 # no, continue + + lda 2,41 # get new fp + sta 2,40 # restore stack + sta 3,41 # restore old fp + jmp @40 # Return + +Assembler syntax and functions. + +The assembler syntax mimics the DG assembler. +Load and store to addresses is written "lda 0,foo" to load from address foo. +If foo is not in zero page then the assembler will put the lda in the +text area close to the instruction and do an indirect pc-relative load. + diff --git a/compilers/pcc/pcc-1.0.0/arch/nova/code.c b/compilers/pcc/pcc-1.0.0/arch/nova/code.c new file mode 100644 index 00000000..9a6cc0e2 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/nova/code.c @@ -0,0 +1,193 @@ +/* $Id: code.c,v 1.5 2008/01/01 17:31:00 ragge Exp $ */ +/* + * Copyright (c) 2006 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass1.h" + +/* + * cause the alignment to become a multiple of n + * never called for text segment. + */ +void +defalign(int n) +{ + /* alignment are always correct */ +} + +/* + * define the current location as the name p->soname + * never called for text segment. + */ +void +defnam(struct symtab *p) +{ + char *c = p->soname; + + if (p->sclass == EXTDEF) + printf(" .globl %s\n", c); + printf("%s:\n", c); +} + + +/* + * code for the end of a function + * deals with struct return here + */ +void +efcode() +{ + NODE *p, *q; + int sz; + + if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) + return; +cerror("efcode"); + /* address of return struct is in eax */ + /* create a call to memcpy() */ + /* will get the result in eax */ + p = block(REG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR)); +// p->n_rval = EAX; + q = block(OREG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR)); +// q->n_rval = EBP; + q->n_lval = 8; /* return buffer offset */ + p = block(CM, q, p, INT, 0, MKSUE(INT)); + sz = (tsize(STRTY, cftnsp->sdf, cftnsp->ssue)+SZCHAR-1)/SZCHAR; + p = block(CM, p, bcon(sz), INT, 0, MKSUE(INT)); + p->n_right->n_name = ""; + p = block(CALL, bcon(0), p, CHAR+PTR, 0, MKSUE(CHAR+PTR)); + p->n_left->n_name = "memcpy"; + p = clocal(p); + send_passt(IP_NODE, p); +} + +/* + * code for the beginning of a function; a is an array of + * indices in symtab for the arguments; n is the number + */ +void +bfcode(struct symtab **a, int n) +{ + int i; + + if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) + return; +cerror("bfcode"); + /* Function returns struct, adjust arg offset */ + for (i = 0; i < n; i++) + a[i]->soffset += SZPOINT(INT); +} + + +/* + * by now, the automatics and register variables are allocated + */ +void +bccode() +{ + SETOFF(autooff, SZINT); +} + +/* called just before final exit */ +/* flag is 1 if errors, 0 if none */ +void +ejobcode(int flag ) +{ +} + +void +bjobcode() +{ +} + +/* + * Print character t at position i in one string, until t == -1. + * Locctr & label is already defined. + */ +void +bycode(int t, int i) +{ + static int lastoctal = 0; + + /* put byte i+1 in a string */ + + if (t < 0) { + if (i != 0) + puts("\""); + } else { + if (i == 0) + printf("\t.ascii \""); + if (t == '\\' || t == '"') { + lastoctal = 0; + putchar('\\'); + putchar(t); + } else if (t < 040 || t >= 0177) { + lastoctal++; + printf("\\%o",t); + } else if (lastoctal && '0' <= t && t <= '9') { + lastoctal = 0; + printf("\"\n\t.ascii \"%c", t); + } else { + lastoctal = 0; + putchar(t); + } + } +} + +/* + * return the alignment of field of type t + */ +int +fldal(unsigned int t) +{ + uerror("illegal field type"); + return(ALINT); +} + +/* fix up type of field p */ +void +fldty(struct symtab *p) +{ +} + +/* + * XXX - fix genswitch. + */ +int +mygenswitch(int num, TWORD type, struct swents **p, int n) +{ + return 0; +} +/* + * Called with a function call with arguments as argument. + * This is done early in buildtree() and only done once. + */ +NODE * +funcode(NODE *p) +{ + return p; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/nova/local.c b/compilers/pcc/pcc-1.0.0/arch/nova/local.c new file mode 100644 index 00000000..28c5445d --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/nova/local.c @@ -0,0 +1,650 @@ +/* $Id: local.c,v 1.8 2011/01/21 21:47:58 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass1.h" + +/* this file contains code which is dependent on the target machine */ + +NODE * +clocal(NODE *p) +{ + struct symtab *q; + NODE *r, *l; + int o; + + switch( o = p->n_op ){ + case NAME: + /* handle variables */ + if ((q = p->n_sp) == NULL) + return p; /* Nothing to care about */ + switch (q->sclass) { + case AUTO: + /* fake up a structure reference */ + r = block(REG, NIL, NIL, PTR+STRTY, 0, 0); + r->n_lval = 0; + r->n_rval = FPREG; + p = stref(block(STREF, r, p, 0, 0, 0)); + break; + default: + break; + } + break; + + case PMCONV: + case PVCONV: + if( p->n_right->n_op != ICON ) cerror( "bad conversion", 0); + nfree(p); + return(buildtree(o==PMCONV?MUL:DIV, p->n_left, p->n_right)); + + case PCONV: + l = p->n_left; + /* if conversion to another pointer type, just remove */ + if (p->n_type > BTMASK && l->n_type > BTMASK) + goto delp; + break; + + delp: l->n_type = p->n_type; + l->n_qual = p->n_qual; + l->n_df = p->n_df; + l->n_sue = p->n_sue; + nfree(p); + p = l; + break; + } + +#if 0 + register struct symtab *q; + register NODE *r, *l; + register int o; + register int m; + TWORD t; + +//printf("in:\n"); +//fwalk(p, eprint, 0); + switch( o = p->n_op ){ + + case NAME: + if ((q = p->n_sp) == NULL) + return p; /* Nothing to care about */ + + switch (q->sclass) { + + case PARAM: + case AUTO: + /* fake up a structure reference */ + r = block(REG, NIL, NIL, PTR+STRTY, 0, 0); + r->n_lval = 0; + r->n_rval = FPREG; + p = stref(block(STREF, r, p, 0, 0, 0)); + break; + + case STATIC: + if (q->slevel == 0) + break; + p->n_lval = 0; + p->n_sp = q; + break; + + case REGISTER: + p->n_op = REG; + p->n_lval = 0; + p->n_rval = q->soffset; + break; + + } + break; + + case STCALL: + case CALL: + /* Fix function call arguments. On x86, just add funarg */ + for (r = p->n_right; r->n_op == CM; r = r->n_left) { + if (r->n_right->n_op != STARG && + r->n_right->n_op != FUNARG) + r->n_right = block(FUNARG, r->n_right, NIL, + r->n_right->n_type, r->n_right->n_df, + r->n_right->n_sue); + } + if (r->n_op != STARG && r->n_op != FUNARG) { + l = talloc(); + *l = *r; + r->n_op = FUNARG; r->n_left = l; r->n_type = l->n_type; + } + break; + + case CBRANCH: + l = p->n_left; + + /* + * Remove unnecessary conversion ops. + */ + if (clogop(l->n_op) && l->n_left->n_op == SCONV) { + if (coptype(l->n_op) != BITYPE) + break; + if (l->n_right->n_op == ICON) { + r = l->n_left->n_left; + if (r->n_type >= FLOAT && r->n_type <= LDOUBLE) + break; + /* Type must be correct */ + t = r->n_type; + nfree(l->n_left); + l->n_left = r; + l->n_type = t; + l->n_right->n_type = t; + } + } + break; + + case PCONV: + /* Remove redundant PCONV's. Be careful */ + l = p->n_left; + if (l->n_op == ICON) { + l->n_lval = (unsigned)l->n_lval; + goto delp; + } + if (l->n_type < INT || l->n_type == LONGLONG || + l->n_type == ULONGLONG) { + /* float etc? */ + p->n_left = block(SCONV, l, NIL, + UNSIGNED, 0, MKSUE(UNSIGNED)); + break; + } + /* if left is SCONV, cannot remove */ + if (l->n_op == SCONV) + break; + /* if conversion to another pointer type, just remove */ + if (p->n_type > BTMASK && l->n_type > BTMASK) + goto delp; + break; + + delp: l->n_type = p->n_type; + l->n_qual = p->n_qual; + l->n_df = p->n_df; + l->n_sue = p->n_sue; + nfree(p); + p = l; + break; + + case SCONV: + l = p->n_left; + + if (p->n_type == l->n_type) { + nfree(p); + return l; + } + + if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 && + btdims[p->n_type].suesize == btdims[l->n_type].suesize) { + if (p->n_type != FLOAT && p->n_type != DOUBLE && + l->n_type != FLOAT && l->n_type != DOUBLE && + l->n_type != LDOUBLE && p->n_type != LDOUBLE) { + if (l->n_op == NAME || l->n_op == UMUL || + l->n_op == TEMP) { + l->n_type = p->n_type; + nfree(p); + return l; + } + } + } + + if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT && + coptype(l->n_op) == BITYPE) { + l->n_type = p->n_type; + nfree(p); + return l; + } + + o = l->n_op; + m = p->n_type; + + if (o == ICON) { + CONSZ val = l->n_lval; + + if (!ISPTR(m)) /* Pointers don't need to be conv'd */ + switch (m) { + case CHAR: + l->n_lval = (char)val; + break; + case UCHAR: + l->n_lval = val & 0377; + break; + case SHORT: + l->n_lval = (short)val; + break; + case USHORT: + l->n_lval = val & 0177777; + break; + case ULONG: + case UNSIGNED: + l->n_lval = val & 0xffffffff; + break; + case LONG: + case INT: + l->n_lval = (int)val; + break; + case LONGLONG: + l->n_lval = (long long)val; + break; + case ULONGLONG: + l->n_lval = val; + break; + case VOID: + break; + case LDOUBLE: + case DOUBLE: + case FLOAT: + l->n_op = FCON; + l->n_dcon = val; + break; + default: + cerror("unknown type %d", m); + } + l->n_type = m; + l->n_sue = MKSUE(m); + nfree(p); + return l; + } + if (DEUNSIGN(p->n_type) == SHORT && + DEUNSIGN(l->n_type) == SHORT) { + nfree(p); + p = l; + } + if ((p->n_type == CHAR || p->n_type == UCHAR || + p->n_type == SHORT || p->n_type == USHORT) && + (l->n_type == FLOAT || l->n_type == DOUBLE || + l->n_type == LDOUBLE)) { + p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_sue); + p->n_left->n_type = INT; + return p; + } + break; + + case MOD: + case DIV: + if (o == DIV && p->n_type != CHAR && p->n_type != SHORT) + break; + if (o == MOD && p->n_type != CHAR && p->n_type != SHORT) + break; + /* make it an int division by inserting conversions */ + p->n_left = block(SCONV, p->n_left, NIL, INT, 0, MKSUE(INT)); + p->n_right = block(SCONV, p->n_right, NIL, INT, 0, MKSUE(INT)); + p = block(SCONV, p, NIL, p->n_type, 0, MKSUE(p->n_type)); + p->n_left->n_type = INT; + break; + + case PMCONV: + case PVCONV: + if( p->n_right->n_op != ICON ) cerror( "bad conversion", 0); + nfree(p); + return(buildtree(o==PMCONV?MUL:DIV, p->n_left, p->n_right)); + + case FORCE: + /* put return value in return reg */ + p->n_op = ASSIGN; + p->n_right = p->n_left; + p->n_left = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT)); + p->n_left->n_rval = RETREG(p->n_type); + break; + + case LS: + case RS: + /* shift count must be in a char + * unless longlong, where it must be int */ + if (p->n_right->n_op == ICON) + break; /* do not do anything */ + if (p->n_type == LONGLONG || p->n_type == ULONGLONG) { + if (p->n_right->n_type != INT) + p->n_right = block(SCONV, p->n_right, NIL, + INT, 0, MKSUE(INT)); + break; + } + if (p->n_right->n_type == CHAR || p->n_right->n_type == UCHAR) + break; + p->n_right = block(SCONV, p->n_right, NIL, + CHAR, 0, MKSUE(CHAR)); + break; + } +//printf("ut:\n"); +//fwalk(p, eprint, 0); + +#endif + + return(p); +} + +void +myp2tree(NODE *p) +{ + struct symtab *sp; + int o = p->n_op, i; + + if (o != FCON) + return; + + sp = inlalloc(sizeof(struct symtab)); + sp->sclass = STATIC; + sp->ssue = MKSUE(p->n_type); + sp->slevel = 1; /* fake numeric label */ + sp->soffset = getlab(); + sp->sflags = 0; + sp->stype = p->n_type; + sp->squal = (CON >> TSHIFT); + + defloc(sp); + ninval(0, sp->ssue->suesize, p); + + p->n_op = NAME; + p->n_lval = 0; + p->n_sp = sp; + +} + +/*ARGSUSED*/ +int +andable(NODE *p) +{ + return(1); /* all names can have & taken on them */ +} + +/* + * at the end of the arguments of a ftn, set the automatic offset + */ +void +cendarg() +{ + autooff = AUTOINIT; +} + +/* + * Return 1 if a variable of type type is OK to put in register. + */ +int +cisreg(TWORD t) +{ + return 1; /* try to put anything in a register */ +} + +/* + * return a node, for structure references, which is suitable for + * being added to a pointer of type t, in order to be off bits offset + * into a structure + * t, d, and s are the type, dimension offset, and sizeoffset + * For nova, return the type-specific index number which calculation + * is based on its size. For example, char a[3] would return 3. + * Be careful about only handling first-level pointers, the following + * indirections must be fullword. + */ +NODE * +offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue) +{ + register NODE *p; + + if (xdebug) + printf("offcon: OFFSZ %ld type %x dim %p siz %d\n", + off, t, d, sue->suesize); + + p = bcon(0); + p->n_lval = off/SZINT; /* Default */ + if (ISPTR(DECREF(t))) + return p; + if (t == VOID || t == CHAR || t == UCHAR) + p->n_lval = off/SZCHAR; /* pointer to char */ + return(p); +} + +/* + * Allocate off bits on the stack. p is a tree that when evaluated + * is the multiply count for off, t is a NAME node where to write + * the allocated address. + */ +void +spalloc(NODE *t, NODE *p, OFFSZ off) +{ + NODE *sp; + +cerror("spalloc"); + if ((off % SZINT) == 0) + p = buildtree(MUL, p, bcon(off/SZINT)); + else if ((off % SZSHORT) == 0) { + p = buildtree(MUL, p, bcon(off/SZSHORT)); + p = buildtree(PLUS, p, bcon(1)); + p = buildtree(RS, p, bcon(1)); + } else if ((off % SZCHAR) == 0) { + p = buildtree(MUL, p, bcon(off/SZCHAR)); + p = buildtree(PLUS, p, bcon(3)); + p = buildtree(RS, p, bcon(2)); + } else + cerror("roundsp"); + + /* save the address of sp */ + sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_sue); + sp->n_lval = 0; + sp->n_rval = STKREG; + t->n_type = sp->n_type; + ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */ + + /* add the size to sp */ + sp = block(REG, NIL, NIL, p->n_type, 0, 0); + sp->n_lval = 0; + sp->n_rval = STKREG; + ecomp(buildtree(PLUSEQ, sp, p)); +} + +/* + * print out a constant node + * mat be associated with a label + */ +void +ninval(NODE *p) +{ + struct symtab *q; + TWORD t; + + p = p->n_left; + t = p->n_type; + if (t > BTMASK) + t = INT; /* pointer */ + + if (p->n_op != ICON) + cerror("ninval: init node not constant"); + + switch (t) { + case LONG: + case ULONG: + inval(p->n_lval & 0xffff); + inval(p->n_lval >> 16); + break; + case INT: + case UNSIGNED: + printf("\t.word 0%o", (short)p->n_lval); + if ((q = p->n_sp) != NULL) { + if ((q->sclass == STATIC && q->slevel > 0)) { + printf("+" LABFMT, q->soffset); + } else + printf("+%s", exname(q->soname)); + } + printf("\n"); + break; + default: + cerror("ninval"); + } +} + +/* + * print out an integer. + */ +void +inval(CONSZ word) +{ + word &= 0xffff; + printf(" .word 0%o\n", (int)word); +} + +/* output code to initialize a floating point value */ +/* the proper alignment has been obtained */ +void +finval(NODE *p) +{ + union { float f; double d; long double l; int i[3]; } u; + +cerror("finval"); + switch (p->n_type) { + case LDOUBLE: + u.i[2] = 0; + u.l = (long double)p->n_dcon; + printf("\t.long\t0x%x,0x%x,0x%x\n", u.i[0], u.i[1], u.i[2]); + break; + case DOUBLE: + u.d = (double)p->n_dcon; + printf("\t.long\t0x%x,0x%x\n", u.i[0], u.i[1]); + break; + case FLOAT: + u.f = (float)p->n_dcon; + printf("\t.long\t0x%x\n", u.i[0]); + break; + } +} + +/* make a name look like an external name in the local machine */ +char * +exname(char *p) +{ + if (p == NULL) + return ""; + return p; +} + +/* + * map types which are not defined on the local machine + */ +TWORD +ctype(TWORD type) +{ + switch (BTYPE(type)) { + case LONGLONG: + MODTYPE(type,LONG); + break; + + case ULONGLONG: + MODTYPE(type,ULONG); + break; + case SHORT: + MODTYPE(type,INT); + break; + case USHORT: + MODTYPE(type,UNSIGNED); + break; + } + return (type); +} + +/* curid is a variable which is defined but + * is not initialized (and not a function ); + * This routine returns the storage class for an uninitialized declaration + */ +int +noinit() +{ + return(EXTERN); +} + +void +calldec(NODE *p, NODE *q) +{ +} + +void +extdec(struct symtab *q) +{ +} + +/* make a common declaration for id, if reasonable */ +void +commdec(struct symtab *q) +{ + int off; + + off = tsize(q->stype, q->sdf, q->ssue); + off = (off+(SZCHAR-1))/SZCHAR; + printf(" .comm %s,0%o\n", exname(q->soname), off); +} + +/* make a local common declaration for id, if reasonable */ +void +lcommdec(struct symtab *q) +{ + int off; + + off = tsize(q->stype, q->sdf, q->ssue); + off = (off+(SZCHAR-1))/SZCHAR; + if (q->slevel == 0) + printf(" .lcomm %s,0%o\n", exname(q->soname), off); + else + printf(" .lcomm " LABFMT ",0%o\n", q->soffset, off); +} + +/* + * print a (non-prog) label. + */ +void +deflab1(int label) +{ + printf(LABFMT ":\n", label); +} + +static char *loctbl[] = { "text", "data", "section .rodata", "section .rodata" }; + +void +setloc1(int locc) +{ + if (locc == lastloc) + return; + lastloc = locc; + printf(" .%s\n", loctbl[locc]); +} +/* + * Give target the opportunity of handling pragmas. + */ +int +mypragma(char *str) +{ + return 0; +} + +/* + * Called when a identifier has been declared, to give target last word. + */ +void +fixdef(struct symtab *sp) +{ +} + +void +pass1_lastchance(struct interpass *ip) +{ +} diff --git a/compilers/pcc/pcc-1.0.0/arch/nova/local2.c b/compilers/pcc/pcc-1.0.0/arch/nova/local2.c new file mode 100644 index 00000000..6fc36482 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/nova/local2.c @@ -0,0 +1,580 @@ +/* $Id: local2.c,v 1.7 2008/11/01 08:29:37 mickey Exp $ */ +/* + * Copyright (c) 2006 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass2.h" +# include +# include + +void acon(NODE *p); +int argsize(NODE *p); + +void +deflab(int label) +{ + printf(LABFMT ":\n", label); +} + +static int prolnum; +static struct ldq { + struct ldq *next; + int val; + int lab; + char *name; +} *ldq; + + +void +prologue(struct interpass_prolog *ipp) +{ + int i, j; + + for (j = i = 0; i < MAXREGS; i++) + if (TESTBIT(ipp->ipp_regs, i)) + j++; + + printf(".LP%d: .word 0%o\n", prolnum, j); + if (ipp->ipp_vis) + printf(" .globl %s\n", ipp->ipp_name); + printf("%s:\n", ipp->ipp_name); + printf(" sta 3,@40\n"); /* save ret pc on stack */ + printf(" lda 2,.LP%d-.,1\n", prolnum); + printf(" jsr @45\n"); + prolnum++; +} + +void +eoftn(struct interpass_prolog *ipp) +{ + int i, j; + + if (ipp->ipp_ip.ip_lbl == 0) + return; /* no code needs to be generated */ + + /* return from function code */ + for (j = i = 0; i < MAXREGS; i++) + if (TESTBIT(ipp->ipp_regs, i)) + j++; + printf(" lda 2,.LP%d-.,1\n", prolnum); + printf(" jmp @46\n"); + printf(".LP%d: .word 0%o\n", prolnum, j); + prolnum++; + while (ldq) { + printf(".LP%d: .word 0%o", ldq->lab, ldq->val); + if (ldq->name && *ldq->name) + printf("+%s", ldq->name); + printf("\n"); + ldq = ldq->next; + } +} + +/* + * add/sub/... + * + * Param given: + */ +void +hopcode(int f, int o) +{ + char *str = 0; + + switch (o) { + case PLUS: + str = "add"; + break; + case MINUS: + str = "sub"; + break; + case AND: + str = "and"; + break; + case OR: + cerror("hopcode OR"); + break; + case ER: + cerror("hopcode xor"); + str = "xor"; + break; + default: + comperr("hopcode2: %d", o); + str = 0; /* XXX gcc */ + } + printf("%s%c", str, f); +} + +#if 0 +/* + * Return type size in bytes. Used by R2REGS, arg 2 to offset(). + */ +int +tlen(p) NODE *p; +{ + switch(p->n_type) { + case CHAR: + case UCHAR: + return(1); + + case SHORT: + case USHORT: + return(SZSHORT/SZCHAR); + + case DOUBLE: + return(SZDOUBLE/SZCHAR); + + case INT: + case UNSIGNED: + case LONG: + case ULONG: + return(SZINT/SZCHAR); + + case LONGLONG: + case ULONGLONG: + return SZLONGLONG/SZCHAR; + + default: + if (!ISPTR(p->n_type)) + comperr("tlen type %d not pointer"); + return SZPOINT(p->n_type)/SZCHAR; + } +} +#endif + +int +fldexpand(NODE *p, int cookie, char **cp) +{ + return 0; +} + +#if 0 +/* + * Assign to a bitfield. + * Clumsy at least, but what to do? + */ +static void +bfasg(NODE *p) +{ + NODE *fn = p->n_left; + int shift = UPKFOFF(fn->n_rval); + int fsz = UPKFSZ(fn->n_rval); + int andval, tch = 0; + + /* get instruction size */ + switch (p->n_type) { + case CHAR: case UCHAR: tch = 'b'; break; + case SHORT: case USHORT: tch = 'w'; break; + case INT: case UNSIGNED: tch = 'l'; break; + default: comperr("bfasg"); + } + + /* put src into a temporary reg */ + fprintf(stdout, " mov%c ", tch); + adrput(stdout, getlr(p, 'R')); + fprintf(stdout, ","); + adrput(stdout, getlr(p, '1')); + fprintf(stdout, "\n"); + + /* AND away the bits from dest */ + andval = ~(((1 << fsz) - 1) << shift); + fprintf(stdout, " and%c $%d,", tch, andval); + adrput(stdout, fn->n_left); + fprintf(stdout, "\n"); + + /* AND away unwanted bits from src */ + andval = ((1 << fsz) - 1); + fprintf(stdout, " and%c $%d,", tch, andval); + adrput(stdout, getlr(p, '1')); + fprintf(stdout, "\n"); + + /* SHIFT left src number of bits */ + if (shift) { + fprintf(stdout, " sal%c $%d,", tch, shift); + adrput(stdout, getlr(p, '1')); + fprintf(stdout, "\n"); + } + + /* OR in src to dest */ + fprintf(stdout, " or%c ", tch); + adrput(stdout, getlr(p, '1')); + fprintf(stdout, ","); + adrput(stdout, fn->n_left); + fprintf(stdout, "\n"); +} +#endif + +#if 0 +/* + * Push a structure on stack as argument. + * the scratch registers are already free here + */ +static void +starg(NODE *p) +{ + FILE *fp = stdout; + + fprintf(fp, " subl $%d,%%esp\n", p->n_stsize); + fprintf(fp, " pushl $%d\n", p->n_stsize); + expand(p, 0, " pushl AL\n"); + expand(p, 0, " leal 8(%esp),A1\n"); + expand(p, 0, " pushl A1\n"); + fprintf(fp, " call memcpy\n"); + fprintf(fp, " addl $12,%%esp\n"); +} +#endif + +void +zzzcode(NODE *p, int c) +{ + struct ldq *ld; + + switch (c) { + case 'A': /* print out a skip ending if any numbers in queue */ + if (ldq == NULL) + return; + printf(",skp\n.LP%d: .word 0%o", ldq->lab, ldq->val); + if (ldq->name && *ldq->name) + printf("+%s", ldq->name); + printf("\n"); + ldq = ldq->next; + break; + + case 'B': /* print a label for later load */ + ld = tmpalloc(sizeof(struct ldq)); + ld->val = p->n_lval; + ld->name = p->n_name; + ld->lab = prolnum++; + ld->next = ldq; + ldq = ld; + printf(".LP%d-.", ld->lab); + break; + + case 'C': /* fix reference to external variable via indirection */ + zzzcode(p->n_left, 'B'); + break; + + case 'D': /* fix reference to external variable via indirection */ + zzzcode(p, 'B'); + break; + + default: + comperr("zzzcode %c", c); + } +} + +/*ARGSUSED*/ +int +rewfld(NODE *p) +{ + return(1); +} + +int canaddr(NODE *); +int +canaddr(NODE *p) +{ + int o = p->n_op; + + if (o==NAME || o==REG || o==ICON || o==OREG || + (o==UMUL && shumul(p->n_left, SOREG))) + return(1); + return(0); +} + +/* + * Does the bitfield shape match? + */ +int +flshape(NODE *p) +{ + int o = p->n_op; + +cerror("flshape"); + if (o == OREG || o == REG || o == NAME) + return SRDIR; /* Direct match */ + if (o == UMUL && shumul(p->n_left, SOREG)) + return SROREG; /* Convert into oreg */ + return SRREG; /* put it into a register */ +} + +/* INTEMP shapes must not contain any temporary registers */ +/* XXX should this go away now? */ +int +shtemp(NODE *p) +{ + return 0; +#if 0 + int r; + + if (p->n_op == STARG ) + p = p->n_left; + + switch (p->n_op) { + case REG: + return (!istreg(p->n_rval)); + + case OREG: + r = p->n_rval; + if (R2TEST(r)) { + if (istreg(R2UPK1(r))) + return(0); + r = R2UPK2(r); + } + return (!istreg(r)); + + case UMUL: + p = p->n_left; + return (p->n_op != UMUL && shtemp(p)); + } + + if (optype(p->n_op) != LTYPE) + return(0); + return(1); +#endif +} + +void +adrcon(CONSZ val) +{ + printf("$" CONFMT, val); +} + +/* + * Conput should only be used by e2print on Nova. + */ +void +conput(FILE *fp, NODE *p) +{ + int val = p->n_lval; + + switch (p->n_op) { + case ICON: + if (p->n_name[0] != '\0') { + fprintf(fp, "%s", p->n_name); + if (val) + fprintf(fp, "+%d", val); + } else + fprintf(fp, "%d", val); + return; + + default: + comperr("illegal conput, p %p", p); + } +} + +/*ARGSUSED*/ +void +insput(NODE *p) +{ + comperr("insput"); +} + +/* + * Write out the upper address, like the upper register of a 2-register + * reference, or the next memory location. + */ +void +upput(NODE *p, int size) +{ +comperr("upput"); +#if 0 + size /= SZCHAR; + switch (p->n_op) { + case REG: + fprintf(stdout, "%%%s", &rnames[p->n_rval][3]); + break; + + case NAME: + case OREG: + p->n_lval += size; + adrput(stdout, p); + p->n_lval -= size; + break; + case ICON: + fprintf(stdout, "$" CONFMT, p->n_lval >> 32); + break; + default: + comperr("upput bad op %d size %d", p->n_op, size); + } +#endif +} + +void +adrput(FILE *io, NODE *p) +{ + /* output an address, with offsets, from p */ + + if (p->n_op == FLD) + p = p->n_left; + + switch (p->n_op) { + + case NAME: + if (p->n_name[0] != '\0') + fputs(p->n_name, io); + if (p->n_lval != 0) + fprintf(io, "+" CONFMT, p->n_lval); + return; + + case OREG: + printf("%d,%s", (int)p->n_lval, rnames[p->n_rval]); + return; + + case ICON: + /* addressable value of the constant */ + fputc('$', io); + conput(io, p); + return; + + case MOVE: + case REG: + switch (p->n_type) { + case LONGLONG: + case ULONGLONG: + fprintf(io, "%%%c%c%c", rnames[p->n_rval][0], + rnames[p->n_rval][1], rnames[p->n_rval][2]); + break; + case SHORT: + case USHORT: + fprintf(io, "%%%s", &rnames[p->n_rval][2]); + break; + default: + fprintf(io, "%s", rnames[p->n_rval]); + } + return; + + default: + comperr("illegal address, op %d, node %p", p->n_op, p); + return; + + } +} + +/* printf conditional and unconditional branches */ +void +cbgen(int o, int lab) +{ + comperr("cbgen"); +} + +void +myreader(struct interpass *ipole) +{ + if (x2debug) + printip(ipole); +} + +void +mycanon(NODE *p) +{ +} + +void +myoptim(struct interpass *ip) +{ +} + +void +rmove(int s, int d, TWORD t) +{ + comperr("rmove"); +} + +/* + * For class c, find worst-case displacement of the number of + * registers in the array r[] indexed by class. + * Return true if we always can find a color. + */ +int +COLORMAP(int c, int *r) +{ + int num; + + switch (c) { + case CLASSA: + num = r[CLASSB] + r[CLASSA]; + return num < 4; + case CLASSB: + num = r[CLASSB] + r[CLASSA]; + return num < 2; + case CLASSC: + return r[CLASSC] < CREGCNT; + case CLASSD: + return r[CLASSD] < DREGCNT; + } + return 0; /* XXX gcc */ +} + +char *rnames[] = { + "0", "1", "2", "3", + "050", "051", "052", "053", "054", "055", "056", "057", + "060", "061", "062", "063", "064", "065", "066", "067", + "070", "071", "072", "073", "074", "075", "076", "077", + "041", "040" +}; + +/* + * Return a class suitable for a specific type. + */ +int +gclass(TWORD t) +{ + return CLASSA; +} + +/* + * Calculate argument sizes. + */ +void +lastcall(NODE *p) +{ +} + +/* + * Special shapes. + */ +int +special(NODE *p, int shape) +{ + return SRNOPE; +} + +/* + * Target-dependent command-line options. + */ +void +mflags(char *str) +{ +} +/* + * Do something target-dependent for xasm arguments. + * Supposed to find target-specific constraints and rewrite them. + */ +int +myxasm(struct interpass *ip, NODE *p) +{ + return 0; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/nova/macdefs.h b/compilers/pcc/pcc-1.0.0/arch/nova/macdefs.h new file mode 100644 index 00000000..4581be4b --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/nova/macdefs.h @@ -0,0 +1,189 @@ +/* $Id: macdefs.h,v 1.2 2007/11/16 22:27:42 gmcgarry Exp $ */ +/* + * Copyright (c) 2006 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Machine-dependent defines for Data General Nova. + */ + +/* + * Convert (multi-)character constant to integer. + */ +#define makecc(val,i) lastcon = (lastcon<<8)|(val); + +#define ARGINIT 16 /* adjusted in MD code */ +#define AUTOINIT 16 /* adjusted in MD code */ + +/* + * Storage space requirements + */ +#define SZCHAR 8 +#define SZINT 16 +#define SZFLOAT 32 +#define SZDOUBLE 64 +#define SZLDOUBLE 64 +#define SZLONG 32 +#define SZSHORT 16 +#define SZLONGLONG 32 +#define SZPOINT(t) 16 /* Actually 15 */ + +/* + * Alignment constraints + */ +#define ALCHAR 8 +#define ALINT 16 +#define ALFLOAT 16 +#define ALDOUBLE 16 +#define ALLDOUBLE 16 +#define ALLONG 16 +#define ALLONGLONG 16 +#define ALSHORT 16 +#define ALPOINT 16 +#define ALSTRUCT 16 +#define ALSTACK 16 + +/* + * Min/max values. + */ +#define MIN_CHAR -128 +#define MAX_CHAR 127 +#define MAX_UCHAR 255 +#define MIN_SHORT -32768 +#define MAX_SHORT 32767 +#define MAX_USHORT 65535 +#define MIN_INT MIN_SHORT +#define MAX_INT MAX_SHORT +#define MAX_UNSIGNED MAX_USHORT +#define MIN_LONG 0x80000000L +#define MAX_LONG 0x7fffffffL +#define MAX_ULONG 0xffffffffUL +#define MIN_LONGLONG MIN_LONG +#define MAX_LONGLONG MAX_LONG +#define MAX_ULONGLONG MAX_ULONG + +/* Default char is unsigned */ +#define CHAR_UNSIGNED + +/* + * Use large-enough types. + */ +typedef long CONSZ; +typedef unsigned long U_CONSZ; +typedef long OFFSZ; + +#define CONFMT "%ld" /* format for printing constants */ +#define LABFMT ".L%d" /* format for printing labels */ +#define STABLBL ".LL%d" /* format for stab (debugging) labels */ +#ifdef FORTRAN +#define XL 8 +#define FLABELFMT "%s:\n" +#define USETEXT ".text" +#define USECONST ".data\t0" /* XXX - fix */ +#define USEBSS ".data\t1" /* XXX - fix */ +#define USEINIT ".data\t2" /* XXX - fix */ +#define MAXREGVAR 3 /* XXX - fix */ +#define BLANKCOMMON "_BLNK_" +#define MSKIREG (M(TYSHORT)|M(TYLONG)) +#define TYIREG TYLONG +#define FSZLENG FSZLONG +#define FUDGEOFFSET 1 +#define AUTOREG EBP +#define ARGREG EBP +#define ARGOFFSET 4 +#endif + +#define BACKAUTO /* stack grows negatively for automatics */ +#define BACKTEMP /* stack grows negatively for temporaries */ + +#undef FIELDOPS /* no bit-field instructions */ +#define RTOLBYTES /* bytes are numbered right to left */ + +#define ENUMSIZE(high,low) INT /* enums are always stored in full int */ + +/* Definitions mostly used in pass2 */ + +#define BYTEOFF(x) ((x)&01) +#define wdal(k) (BYTEOFF(k)==0) +#define BITOOR(x) (x) /* bit offset to oreg offset XXX die! */ + +#define STOARG(p) +#define STOFARG(p) +#define STOSTARG(p) +#define genfcall(a,b) gencall(a,b) + +#define szty(t) (((t) == DOUBLE || (t) == LDOUBLE) ? 4 : \ + ((t) == LONGLONG || (t) == ULONGLONG || \ + (t) == LONG || (t) == ULONG) ? 2 : 1) + +/* + * The Nova has three register classes. Note that the space used in + * zero page is considered registers. + * Register 28 and 29 are FP and SP. + * + * The classes used on Nova are: + * A - AC0-AC3 (as non-index registers) : reg 0-3 + * B - AC2-AC3 (as index registers) : reg 2-3 + * C - address 50-77 in memory : reg 4-27 + */ +#define MAXREGS 30 /* 0-29 */ + +#define RSTATUS \ + SAREG|TEMPREG, SAREG|TEMPREG, SAREG|SBREG|TEMPREG, SAREG|SBREG|TEMPREG,\ + SCREG|TEMPREG, SCREG|TEMPREG, SCREG|TEMPREG, SCREG|TEMPREG, \ + SCREG|TEMPREG, SCREG|TEMPREG, SCREG|TEMPREG, SCREG|TEMPREG, \ + SCREG|PERMREG, SCREG|PERMREG, SCREG|PERMREG, SCREG|PERMREG, \ + SCREG|PERMREG, SCREG|PERMREG, SCREG|PERMREG, SCREG|PERMREG, \ + SCREG|PERMREG, SCREG|PERMREG, SCREG|PERMREG, SCREG|PERMREG, \ + SCREG|PERMREG, SCREG|PERMREG, SCREG|PERMREG, SCREG|PERMREG, \ + 0, 0 + +#define ROVERLAP \ + { -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 }, + + +/* Return a register class based on the type of the node */ +/* all types in all classes */ +#define PCLASS(p) (SAREG|SBREG|SCREG) + +#define NUMCLASS 4 /* highest number of reg classes used */ + /* XXX - must be 4 */ + +int COLORMAP(int c, int *r); +#define GCLASS(x) (x < 4 ? CLASSA : CLASSC) +#define DECRA(x,y) (((x) >> (y*6)) & 63) /* decode encoded regs */ +#define ENCRD(x) (x) /* Encode dest reg in n_reg */ +#define ENCRA1(x) ((x) << 6) /* A1 */ +#define ENCRA2(x) ((x) << 12) /* A2 */ +#define ENCRA(x,y) ((x) << (6+y*6)) /* encode regs in int */ +#define RETREG(x) (0) /* ? Sanity */ + +/* XXX - to die */ +#define FPREG 28 /* frame pointer */ +#define STKREG 29 /* stack pointer */ diff --git a/compilers/pcc/pcc-1.0.0/arch/nova/order.c b/compilers/pcc/pcc-1.0.0/arch/nova/order.c new file mode 100644 index 00000000..2373d70d --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/nova/order.c @@ -0,0 +1,186 @@ +/* $Id: order.c,v 1.4 2008/09/27 07:35:23 ragge Exp $ */ +/* + * Copyright (c) 2006 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass2.h" + +#include + +int canaddr(NODE *); + +/* is it legal to make an OREG or NAME entry which has an + * offset of off, (from a register of r), if the + * resulting thing had type t */ +int +notoff(TWORD t, int r, CONSZ off, char *cp) +{ + if (r != 2 && r != 3) + return 1; /* can only index ac2 and ac3 */ + if (t == CHAR || t == UCHAR) { + if (off < -256 || off > 254) + return 1; + } else if (off < -128 || off > 127) + return 1; + return(0); /* YES */ +} + +/* + * Turn a UMUL-referenced node into OREG. + * Be careful about register classes, this is a place where classes change. + */ +void +offstar(NODE *p, int shape) +{ + NODE *r; + + if (x2debug) + printf("offstar(%p)\n", p); + + if (isreg(p)) + return; /* Is already OREG */ + + r = p->n_right; + if( p->n_op == PLUS || p->n_op == MINUS ){ + if( r->n_op == ICON ){ + if (isreg(p->n_left) == 0 || + (p->n_left->n_op == REG && + p->n_left->n_rval != 2 && p->n_left->n_rval != 3)) + (void)geninsn(p->n_left, INBREG); + /* Converted in ormake() */ + return; + } + } + (void)geninsn(p, INBREG); +} + +/* + * Do the actual conversion of offstar-found OREGs into real OREGs. + */ +void +myormake(NODE *q) +{ + if (x2debug) + printf("myormake(%p)\n", q); +} + +/* + * Shape matches for UMUL. Cooperates with offstar(). + */ +int +shumul(NODE *p, int order) +{ + + if (x2debug) + printf("shumul(%p)\n", p); + + /* Turns currently anything into OREG on x86 */ + if (shape & SOREG) + return SROREG; + return SRNOPE; +} + +/* + * Rewrite increment/decrement operation. + */ +int +setincr(NODE *p) +{ + if (x2debug) + printf("setincr(%p)\n", p); + + return(0); +} + +/* + * Rewrite operations on binary operators (like +, -, etc...). + * Called as a result of table lookup. + */ +int +setbin(NODE *p) +{ + + if (x2debug) + printf("setbin(%p)\n", p); + return 0; + +} + +/* setup for assignment operator */ +int +setasg(NODE *p, int cookie) +{ + if (x2debug) + printf("setasg(%p)\n", p); + return(0); +} + +/* setup for unary operator */ +int +setuni(NODE *p, int cookie) +{ + return 0; +} + +/* + * Special handling of some instruction register allocation. + */ +struct rspecial * +nspecial(struct optab *q) +{ + comperr("nspecial entry %d", q - table); + return 0; /* XXX gcc */ +} + +/* + * Set evaluation order of a binary node if it differs from default. + */ +int +setorder(NODE *p) +{ + return 0; +} +/* + * Set registers "live" at function calls (like arguments in registers). + * This is for liveness analysis of registers. + */ +int * +livecall(NODE *p) +{ + static int r[1] = { -1 }; /* Terminate with -1 */ + + return &r[0]; +} + +/* + * Signal whether the instruction is acceptable for this target. + */ +int +acceptable(struct optab *op) +{ + return 1; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/nova/table.c b/compilers/pcc/pcc-1.0.0/arch/nova/table.c new file mode 100644 index 00000000..bbfd24b0 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/nova/table.c @@ -0,0 +1,1514 @@ +/* $Id: table.c,v 1.1 2006/07/30 09:30:48 ragge Exp $ */ +/* + * Copyright (c) 2006 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass2.h" + +# define ANYSIGNED TINT|TLONG|TSHORT|TCHAR +# define ANYUSIGNED TUNSIGNED|TULONG|TUSHORT|TUCHAR +# define ANYFIXED ANYSIGNED|ANYUSIGNED +# define TUWORD TUNSIGNED|TULONG +# define TSWORD TINT|TLONG +# define TWORD TUWORD|TSWORD + +struct optab table[] = { +/* First entry must be an empty entry */ +{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + 0, RDEST, + " mov AR,ALZA\n", }, + +{ ASSIGN, FOREFF|INAREG, + SNAME, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + 0, RDEST, + " sta AR,ZC,1\n", }, + +{ ASSIGN, FOREFF|INAREG, + SOREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + 0, RDEST, + " sta AR,AL\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SONE, TWORD, + NAREG, RESC1, + " subzl A1,A1ZA\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SCON, TWORD, + NAREG, RESC1, + " lda A1,ZB,1\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SZERO, TWORD, + NAREG, RESC1, + " sub A1,A1ZA\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SNAME, TWORD|TPOINT, + NAREG, RESC1, + " lda A1,ZD,1\n", }, + +{ OPLTYPE, INBREG, + SANY, TANY, + SNAME, TWORD|TPOINT, + NBREG, RESC1, + " lda A1,ZD,1\n", }, + +{ OPLTYPE, INBREG, + SANY, TANY, + SCREG, TWORD|TPOINT, + NBREG, RESC1, + " lda A1,AR\n", }, + +{ PLUS, INBREG|INAREG, + SAREG|SBREG, TWORD|TPOINT, + SONE, TANY, + 0, RLEFT, + " inc AL,AL\n", }, + +{ OPSIMP, INBREG|INAREG|FOREFF, + SAREG|SBREG, TWORD|TPOINT, + SAREG|SBREG, TWORD|TPOINT, + 0, RLEFT, + " O AR,AL\n", }, + +{ UMUL, INAREG, + SANY, TPOINT|TWORD, + SOREG, TPOINT|TWORD, + NAREG|NASL, RESC1, + " lda A1,AL\n", }, + +#if 0 + +/* PCONVs are usually not necessary */ +{ PCONV, INAREG, + SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + 0, RLEFT, + "", }, + +/* + * A bunch conversions of integral<->integral types + * There are lots of them, first in table conversions to itself + * and then conversions from each type to the others. + */ + +/* itself to itself, including pointers */ + +/* convert (u)char to (u)char. */ +{ SCONV, INCH, + SHCH, TCHAR|TUCHAR, + SHCH, TCHAR|TUCHAR, + 0, RLEFT, + "", }, + +/* convert pointers to int. */ +{ SCONV, ININT, + SHINT, TPOINT|TWORD, + SANY, TWORD, + 0, RLEFT, + "", }, + +/* convert (u)longlong to (u)longlong. */ +{ SCONV, INLL, + SHLL, TLL, + SHLL, TLL, + 0, RLEFT, + "", }, + +/* convert double <-> float. nothing to do here */ +{ SCONV, INFL, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + 0, RLEFT, + "", }, + +/* convert pointers to pointers. */ +{ SCONV, ININT, + SHINT, TPOINT, + SANY, TPOINT, + 0, RLEFT, + "", }, + +/* char to something */ + +/* convert char to (unsigned) short. */ +{ SCONV, ININT, + SBREG|SOREG|SNAME, TCHAR, + SAREG, TSHORT|TUSHORT, + NASL|NAREG, RESC1, + " movsbw AL,A1\n", }, + +/* convert unsigned char to (u)short. */ +{ SCONV, ININT, + SHCH|SOREG|SNAME, TUCHAR, + SAREG, TSHORT|TUSHORT, + NASL|NAREG, RESC1, + " movzbw AL,A1\n", }, + +/* convert signed char to int (or pointer). */ +{ SCONV, ININT, + SHCH|SOREG|SNAME, TCHAR, + SAREG, TWORD|TPOINT, + NASL|NAREG, RESC1, + " movsbl AL,A1\n", }, + +/* convert unsigned char to (u)int. */ +{ SCONV, ININT, + SHCH|SOREG|SNAME, TUCHAR, + SAREG, TWORD, + NASL|NAREG, RESC1, + " movzbl AL,A1\n", }, + +/* convert char to (u)long long */ +{ SCONV, INLL, + SHCH|SOREG|SNAME, TCHAR, + SANY, TLL, + NSPECIAL|NAREG|NASL, RESC1, + " movsbl AL,%eax\n cltd\n", }, + +/* convert unsigned char to (u)long long */ +{ SCONV, INLL, + SHCH|SOREG|SNAME, TUCHAR, + SANY, TLL, + NCREG|NCSL, RESC1, + " movzbl AL,A1\n xorl U1,U1\n", }, + +/* convert char (in register) to double XXX - use NTEMP */ +{ SCONV, INFL, + SHCH|SOREG|SNAME, TCHAR, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + NAREG|NASL|NDREG, RESC2, + " movsbl AL,A1\n pushl A1\n" + " fildl (%esp)\n addl $4,%esp\n", }, + +/* convert (u)char (in register) to double XXX - use NTEMP */ +{ SCONV, INFL, + SHCH|SOREG|SNAME, TUCHAR, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + NAREG|NASL|NDREG, RESC2, + " movzbl AL,A1\n pushl A1\n" + " fildl (%esp)\n addl $4,%esp\n", }, + +/* short to something */ + +/* convert short (in memory) to char */ +{ SCONV, INCH, + SNAME|SOREG, TSHORT|TUSHORT, + SHCH, TCHAR|TUCHAR, + NBREG|NBSL, RESC1, + " movb AL,A1\n", }, + +/* convert short (in reg) to char. */ +{ SCONV, INCH, + SAREG|SNAME|SOREG, TSHORT|TUSHORT, + SHCH, TCHAR|TUCHAR, + NSPECIAL|NBREG|NBSL, RESC1, + "ZM", }, + +/* convert short to (u)int. */ +{ SCONV, ININT, + SAREG|SOREG|SNAME, TSHORT, + SAREG, TWORD, + NASL|NAREG, RESC1, + " movswl AL,A1\n", }, + +/* convert unsigned short to (u)int. */ +{ SCONV, ININT, + SAREG|SOREG|SNAME, TUSHORT, + SAREG, TWORD, + NASL|NAREG, RESC1, + " movzwl AL,A1\n", }, + +/* convert short to (u)long long */ +{ SCONV, INLL, + SAREG|SOREG|SNAME, TSHORT, + SHLL, TLL, + NSPECIAL|NCREG|NCSL, RESC1, + " movswl AL,%eax\n cltd\n", }, + +/* convert unsigned short to (u)long long */ +{ SCONV, INLL, + SAREG|SOREG|SNAME, TUSHORT, + SHLL, TLL, + NCREG|NCSL, RESC1, + " movzwl AL,A1\n xorl U1,U1\n", }, + +/* convert short (in memory) to float/double */ +{ SCONV, INFL, + SOREG|SNAME, TSHORT, + SDREG, TLDOUBLE|TDOUBLE|TFLOAT, + NDREG, RESC1, + " fild AL\n", }, + +/* convert short (in register) to float/double */ +{ SCONV, INFL, + SAREG, TSHORT, + SDREG, TLDOUBLE|TDOUBLE|TFLOAT, + NTEMP|NDREG, RESC1, + " pushw AL\n fild (%esp)\n addl $2,%esp\n", }, + +/* convert unsigned short to double XXX - use NTEMP */ +{ SCONV, INFL, + SAREG|SOREG|SNAME, TUSHORT, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + NAREG|NASL|NDREG|NTEMP, RESC2, + " movzwl AL,A1\n pushl A1\n" + " fildl (%esp)\n addl $4,%esp\n", }, + +/* int to something */ + +/* convert int to char. This is done when register is loaded */ +{ SCONV, INCH, + SAREG, TWORD, + SANY, TCHAR|TUCHAR, + NSPECIAL|NBREG|NBSL, RESC1, + "ZM", }, + +/* convert int to short. Nothing to do */ +{ SCONV, INAREG, + SAREG, TWORD, + SANY, TSHORT|TUSHORT, + 0, RLEFT, + "", }, + +/* convert int to long long */ +{ SCONV, INLL, + SAREG, TWORD|TPOINT, + SCREG, TLONGLONG, + NSPECIAL|NCREG|NCSL, RESC1, + " cltd\n", }, + +/* convert int to unsigned long long */ +{ SCONV, INLL, + SAREG|SOREG|SNAME, TWORD|TPOINT, + SHLL, TULONGLONG, + NCSL|NCREG, RESC1, + " movl AL,A1\n xorl U1,U1\n", }, + +/* convert int (in memory) to double */ +{ SCONV, INFL, + SOREG|SNAME, TWORD, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + NDREG, RESC1, + " fildl AL\n", }, + +/* convert int (in register) to double */ +{ SCONV, INFL, + SAREG, TWORD, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + NTEMP|NDREG, RESC1, + " pushl AL\n fildl (%esp)\n addl $4,%esp\n", }, + +/* long long to something */ + +/* convert (u)long long to (u)char (mem->reg) */ +{ SCONV, INCH, + SOREG|SNAME, TLL, + SANY, TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " movb AL,A1\n", }, + +/* convert (u)long long to (u)char (reg->reg, hopefully nothing) */ +{ SCONV, INCH, + SHLL, TLL, + SANY, TCHAR|TUCHAR, + NAREG|NASL, RESC1, + "ZS", }, + +/* convert (u)long long to (u)short (mem->reg) */ +{ SCONV, INAREG, + SOREG|SNAME, TLL, + SAREG, TSHORT|TUSHORT, + NAREG|NASL, RESC1, + " movw AL,A1\n", }, + +/* convert (u)long long to (u)short (reg->reg, hopefully nothing) */ +{ SCONV, INAREG, + SHLL|SOREG|SNAME, TLL, + SAREG, TSHORT|TUSHORT, + NAREG|NASL, RESC1, + "ZS", }, + +/* convert long long to int (mem->reg) */ +{ SCONV, INAREG, + SOREG|SNAME, TLL, + SAREG, TWORD|TPOINT, + NAREG|NASL, RESC1, + " movl AL,A1\n", }, + +/* convert long long to int (reg->reg, hopefully nothing) */ +{ SCONV, INAREG, + SHLL|SOREG|SNAME, TLL, + SAREG, TWORD|TPOINT, + NAREG|NASL, RESC1, + "ZS", }, + +/* convert long long (in memory) to floating */ +{ SCONV, INFL, + SOREG|SNAME, TLONGLONG, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + NDREG, RESC1, + " fildq AL\n", }, + +/* convert long long (in register) to floating */ +{ SCONV, INFL, + SHLL, TLONGLONG, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + NTEMP|NDREG, RESC1, + " pushl UL\n pushl AL\n" + " fildq (%esp)\n addl $8,%esp\n", }, + +/* convert unsigned long long to floating */ +{ SCONV, INFL, + SCREG, TULONGLONG, + SDREG, TLDOUBLE|TDOUBLE|TFLOAT, + NDREG, RESC1, + "ZJ", }, + +/* float to something */ + +#if 0 /* go via int by adding an extra sconv in clocal() */ +/* convert float/double to (u) char. XXX should use NTEMP here */ +{ SCONV, INCH, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + SHCH, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NBREG, RESC1, + " subl $4,%esp\n fistpl (%esp)\n popl A1\n", }, + +/* convert float/double to (u) int/short/char. XXX should use NTEMP here */ +{ SCONV, INCH, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + SHCH, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NCREG, RESC1, + " subl $4,%esp\n fistpl (%esp)\n popl A1\n", }, +#endif + +/* convert float/double to (u)int. XXX should use NTEMP here */ +{ SCONV, INAREG, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + SAREG, TWORD, + NAREG, RESC1, + " subl $4,%esp\n fistpl (%esp)\n popl A1\n", }, + +/* convert float/double (in register) to (unsigned) long long */ +/* XXX - unsigned is not handled correct */ +{ SCONV, INLL, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + SHLL, TLONGLONG|TULONGLONG, + NCREG, RESC1, + " subl $8,%esp\n fistpq (%esp)\n" + " popl A1\n popl U1\n", }, + +/* slut sconv */ + +/* + * Subroutine calls. + */ + +{ CALL, FOREFF, + SCON, TANY, + SANY, TANY, + 0, 0, + " call CL\nZC", }, + +{ UCALL, FOREFF, + SCON, TANY, + SAREG, TWORD|TPOINT, + 0, 0, + " call CL\n", }, + +{ CALL, INAREG, + SCON, TANY, + SAREG, TWORD|TPOINT, + NAREG|NASL, RESC1, /* should be 0 */ + " call CL\nZC", }, + +{ UCALL, INAREG, + SCON, TANY, + SAREG, TWORD|TPOINT, + NAREG|NASL, RESC1, /* should be 0 */ + " call CL\n", }, + +{ CALL, INBREG, + SCON, TANY, + SBREG, TCHAR|TUCHAR, + NBREG, RESC1, /* should be 0 */ + " call CL\nZC", }, + +{ UCALL, INBREG, + SCON, TANY, + SBREG, TCHAR|TUCHAR, + NBREG, RESC1, /* should be 0 */ + " call CL\n", }, + +{ CALL, INCREG, + SCON, TANY, + SCREG, TANY, + NCREG|NCSL, RESC1, /* should be 0 */ + " call CL\nZC", }, + +{ UCALL, INCREG, + SCON, TANY, + SCREG, TANY, + NCREG|NCSL, RESC1, /* should be 0 */ + " call CL\n", }, + +{ CALL, INDREG, + SCON, TANY, + SDREG, TANY, + NDREG|NDSL, RESC1, /* should be 0 */ + " call CL\nZC", }, + +{ UCALL, INDREG, + SCON, TANY, + SDREG, TANY, + NDREG|NDSL, RESC1, /* should be 0 */ + " call CL\nZC", }, + +{ CALL, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, 0, + " call *AL\nZC", }, + +{ UCALL, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, 0, + " call *AL\nZC", }, + +{ CALL, INAREG, + SAREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + " call *AL\nZC", }, + +{ UCALL, INAREG, + SAREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + " call *AL\nZC", }, + +{ CALL, INBREG, + SAREG, TANY, + SANY, TANY, + NBREG|NBSL, RESC1, /* should be 0 */ + " call *AL\nZC", }, + +{ UCALL, INBREG, + SAREG, TANY, + SANY, TANY, + NBREG|NBSL, RESC1, /* should be 0 */ + " call *AL\nZC", }, + +{ CALL, INCREG, + SAREG, TANY, + SANY, TANY, + NCREG|NCSL, RESC1, /* should be 0 */ + " call *AL\nZC", }, + +{ UCALL, INCREG, + SAREG, TANY, + SANY, TANY, + NCREG|NCSL, RESC1, /* should be 0 */ + " call *AL\nZC", }, + +{ CALL, INDREG, + SAREG, TANY, + SANY, TANY, + NDREG|NDSL, RESC1, /* should be 0 */ + " call *AL\nZC", }, + +{ UCALL, INDREG, + SAREG, TANY, + SANY, TANY, + NDREG|NDSL, RESC1, /* should be 0 */ + " call *AL\nZC", }, + +/* struct return */ +{ USTCALL, FOREFF, + SCON, TANY, + SANY, TANY, + NAREG|NASL, 0, + "ZP call CL\nZC", }, + +{ USTCALL, INAREG, + SCON, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + "ZP call CL\nZC", }, + +{ USTCALL, INAREG, + SNAME|SAREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + "ZP call *AL\nZC", }, + +{ STCALL, FOREFF, + SCON, TANY, + SANY, TANY, + NAREG|NASL, 0, + "ZP call CL\nZC", }, + +{ STCALL, INAREG, + SCON, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + "ZP call CL\nZC", }, + +{ STCALL, INAREG, + SNAME|SAREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + "ZP call *AL\nZC", }, + +/* + * The next rules handle all binop-style operators. + */ +/* Special treatment for long long */ +{ PLUS, INLL|FOREFF, + SHLL, TLL, + SHLL|SNAME|SOREG, TLL, + 0, RLEFT, + " addl AR,AL\n adcl UR,UL\n", }, + +/* Special treatment for long long XXX - fix commutative check */ +{ PLUS, INLL|FOREFF, + SHLL|SNAME|SOREG, TLL, + SHLL, TLL, + 0, RRIGHT, + " addl AL,AR\n adcl UL,UR\n", }, + +{ PLUS, INFL, + SHFL, TDOUBLE, + SNAME|SOREG, TDOUBLE, + 0, RLEFT, + " faddl AR\n", }, + +{ PLUS, INFL|FOREFF, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + 0, RLEFT, + " faddp\n", }, + +{ PLUS, INAREG, + SAREG|SNAME|SOREG, TWORD|TPOINT, + SONE, TANY, + 0, RLEFT, + " incl AL\n", }, + +{ PLUS, INAREG, + SAREG, TWORD|TPOINT, + SCON, TANY, + NAREG|NASL, RESC1, + " leal CR(AL),A1\n", }, + +{ PLUS, INCH, + SHCH|SNAME|SOREG, TCHAR|TUCHAR, + SONE, TANY, + 0, RLEFT, + " incb AL\n", }, + +{ PLUS, INAREG, + SAREG, TWORD, + SAREG, TWORD, + NAREG|NASL|NASR, RESC1, + " leal (AL,AR),A1\n", }, + + +/* address as register offset, negative */ +{ MINUS, INAREG, + SAREG, TWORD|TPOINT, + SPCON, TANY, + NAREG|NASL, RESC1, + " leal -CR(AL),A1\n", }, + +{ MINUS, INLL|FOREFF, + SHLL, TLL, + SHLL|SNAME|SOREG, TLL, + 0, RLEFT, + " subl AR,AL\n sbbl UR,UL\n", }, + +{ MINUS, INFL, + SHFL, TDOUBLE, + SNAME|SOREG, TDOUBLE, + 0, RLEFT, + " fsubl AR\n", }, + +{ MINUS, INFL|FOREFF, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + 0, RLEFT, + " fsubZAp\n", }, + +/* Simple r/m->reg ops */ +{ OPSIMP, INAREG|FOREFF, + SAREG, TWORD|TPOINT, + SAREG|SNAME|SOREG, TWORD|TPOINT, + 0, RLEFT, + " Ol AR,AL\n", }, + +{ OPSIMP, INAREG|FOREFF, + SHINT, TSHORT|TUSHORT, + SHINT|SNAME|SOREG, TSHORT|TUSHORT, + 0, RLEFT, + " Ow AR,AL\n", }, + +{ OPSIMP, INCH|FOREFF, + SHCH, TCHAR|TUCHAR, + SHCH|SNAME|SOREG, TCHAR|TUCHAR, + 0, RLEFT, + " Ob AR,AL\n", }, + +{ OPSIMP, INAREG|FOREFF, + SAREG, TWORD|TPOINT, + SCON, TWORD|TPOINT, + 0, RLEFT, + " Ol AR,AL\n", }, + +{ OPSIMP, INAREG|FOREFF, + SHINT|SNAME|SOREG, TSHORT|TUSHORT, + SCON, TANY, + 0, RLEFT, + " Ow AR,AL\n", }, + +{ OPSIMP, INCH|FOREFF, + SHCH|SNAME|SOREG, TCHAR|TUCHAR, + SCON, TANY, + 0, RLEFT, + " Ob AR,AL\n", }, + +{ OPSIMP, INLL|FOREFF, + SHLL, TLL, + SHLL|SNAME|SOREG, TLL, + 0, RLEFT, + " Ol AR,AL\n Ol UR,UL\n", }, + + +/* + * The next rules handle all shift operators. + */ +/* (u)longlong left shift is emulated */ +{ LS, INCREG, + SCREG|SNAME|SOREG|SCON, TLL, + SAREG|SNAME|SOREG|SCON, TINT, /* will be int */ + NSPECIAL|NCREG|NCSL|NCSR, RESC1, + "ZO", }, + +{ LS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TWORD, + SHCH, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " sall AR,AL\n", }, + +{ LS, INAREG|FOREFF, + SAREG, TWORD, + SCON, TANY, + 0, RLEFT, + " sall AR,AL\n", }, + +{ LS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TSHORT|TUSHORT, + SHCH, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " shlw AR,AL\n", }, + +{ LS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TSHORT|TUSHORT, + SCON, TANY, + 0, RLEFT, + " shlw AR,AL\n", }, + +{ LS, INCH|FOREFF, + SHCH|SNAME|SOREG, TCHAR|TUCHAR, + SHCH, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " salb AR,AL\n", }, + +{ LS, INCH|FOREFF, + SHCH|SNAME|SOREG, TCHAR|TUCHAR, + SCON, TANY, + 0, RLEFT, + " salb AR,AL\n", }, + +/* (u)longlong right shift is emulated */ +{ RS, INCREG, + SCREG|SNAME|SOREG|SCON, TLL, + SAREG|SNAME|SOREG|SCON, TINT, /* will be int */ + NSPECIAL|NCREG|NCSL|NCSR, RESC1, + "ZO", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TSWORD, + SHCH, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " sarl AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TSWORD, + SCON, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT, + 0, RLEFT, + " sarl AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TUWORD, + SHCH, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " shrl AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TUWORD, + SCON, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT, + 0, RLEFT, + " shrl AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TSHORT, + SHCH, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " sarw AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TSHORT, + SCON, TANY, + 0, RLEFT, + " sarw AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TUSHORT, + SHCH, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " shrw AR,AL\n", }, + +{ RS, INAREG|FOREFF, + SAREG|SNAME|SOREG, TUSHORT, + SCON, TANY, + 0, RLEFT, + " shrw AR,AL\n", }, + +{ RS, INCH|FOREFF, + SHCH|SNAME|SOREG, TCHAR, + SHCH, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " sarb AR,AL\n", }, + +{ RS, INCH|FOREFF, + SHCH|SNAME|SOREG, TCHAR, + SCON, TANY, + 0, RLEFT, + " sarb AR,AL\n", }, + +{ RS, INCH|FOREFF, + SHCH|SNAME|SOREG, TUCHAR, + SHCH, TCHAR|TUCHAR, + NSPECIAL, RLEFT, + " shrb AR,AL\n", }, + +{ RS, INCH|FOREFF, + SHCH|SNAME|SOREG, TUCHAR, + SCON, TANY, + 0, RLEFT, + " shrb AR,AL\n", }, + +/* + * The next rules takes care of assignments. "=". + */ +{ ASSIGN, FOREFF, + SHLL|SNAME|SOREG, TLL, + SCON, TANY, + 0, 0, + " movl AR,AL\n movl UR,UL\n", }, + +{ ASSIGN, FOREFF|INLL, + SHLL, TLL, + SCON, TANY, + 0, RDEST, + " movl AR,AL\n movl UR,UL\n", }, + +{ ASSIGN, FOREFF, + SAREG|SNAME|SOREG, TWORD|TPOINT, + SCON, TANY, + 0, 0, + " movl AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TWORD|TPOINT, + SCON, TANY, + 0, RDEST, + " movl AR,AL\n", }, + +{ ASSIGN, FOREFF, + SAREG|SNAME|SOREG, TSHORT|TUSHORT, + SCON, TANY, + 0, 0, + " movw AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TSHORT|TUSHORT, + SCON, TANY, + 0, RDEST, + " movw AR,AL\n", }, + +{ ASSIGN, FOREFF, + SHCH|SNAME|SOREG, TCHAR|TUCHAR, + SCON, TANY, + 0, 0, + " movb AR,AL\n", }, + +{ ASSIGN, FOREFF|INCH, + SHCH, TCHAR|TUCHAR, + SCON, TANY, + 0, RDEST, + " movb AR,AL\n", }, + +{ ASSIGN, FOREFF|INLL, + SHLL|SNAME|SOREG, TLL, + SHLL, TLL, + 0, RDEST, + " movl AR,AL\n movl UR,UL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG|SNAME|SOREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + 0, RDEST, + " movl AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TWORD|TPOINT, + SAREG|SNAME|SOREG, TWORD|TPOINT, + 0, RDEST, + " movl AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG|SNAME|SOREG, TSHORT|TUSHORT, + SAREG, TSHORT|TUSHORT, + 0, RDEST, + " movw AR,AL\n", }, + +{ ASSIGN, FOREFF|INCH, + SHCH|SNAME|SOREG, TCHAR|TUCHAR, + SHCH, TCHAR|TUCHAR|TWORD, + 0, RDEST, + " movb AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SFLD, TANY, + SAREG, TANY, + NAREG, RDEST, + "ZE", }, + +{ ASSIGN, FOREFF, + SFLD, TANY, + SAREG|SNAME|SOREG|SCON, TANY, + NAREG, 0, + "ZE", }, + +{ ASSIGN, INDREG|FOREFF, + SHFL, TFLOAT|TDOUBLE|TLDOUBLE, + SHFL, TFLOAT|TDOUBLE|TLDOUBLE, + 0, RDEST, + "", }, /* This will always be in the correct register */ + +/* order of table entries is very important here! */ +{ ASSIGN, INFL, + SNAME|SOREG, TLDOUBLE, + SHFL, TFLOAT|TDOUBLE|TLDOUBLE, + 0, RDEST, + " fstt AL\n", }, + +{ ASSIGN, FOREFF, + SNAME|SOREG, TLDOUBLE, + SHFL, TFLOAT|TDOUBLE|TLDOUBLE, + 0, 0, + " fstpt AL\n", }, + +{ ASSIGN, INFL, + SNAME|SOREG, TDOUBLE, + SHFL, TFLOAT|TDOUBLE|TLDOUBLE, + 0, RDEST, + " fstl AL\n", }, + +{ ASSIGN, FOREFF, + SNAME|SOREG, TDOUBLE, + SHFL, TFLOAT|TDOUBLE|TLDOUBLE, + 0, 0, + " fstpl AL\n", }, + +{ ASSIGN, INFL, + SNAME|SOREG, TFLOAT, + SHFL, TFLOAT|TDOUBLE|TLDOUBLE, + 0, RDEST, + " fsts AL\n", }, + +{ ASSIGN, FOREFF, + SNAME|SOREG, TFLOAT, + SHFL, TFLOAT|TDOUBLE|TLDOUBLE, + 0, 0, + " fstps AL\n", }, +/* end very important order */ + +{ ASSIGN, INFL|FOREFF, + SHFL, TLDOUBLE, + SHFL|SOREG|SNAME, TLDOUBLE, + 0, RDEST, + " fldt AR\n", }, + +{ ASSIGN, INFL|FOREFF, + SHFL, TDOUBLE, + SHFL|SOREG|SNAME, TDOUBLE, + 0, RDEST, + " fldl AR\n", }, + +{ ASSIGN, INFL|FOREFF, + SHFL, TFLOAT, + SHFL|SOREG|SNAME, TFLOAT, + 0, RDEST, + " flds AR\n", }, + +/* Do not generate memcpy if return from funcall */ +#if 0 +{ STASG, INAREG|FOREFF, + SOREG|SNAME|SAREG, TPTRTO|TSTRUCT, + SFUNCALL, TPTRTO|TSTRUCT, + 0, RRIGHT, + "", }, +#endif + +{ STASG, INAREG|FOREFF, + SOREG|SNAME, TANY, + SAREG|SOREG|SNAME, TPTRTO|TANY, + NSPECIAL, RRIGHT, + "ZQ", }, + +/* + * DIV/MOD/MUL + */ +/* long long div is emulated */ +{ DIV, INCREG, + SCREG|SNAME|SOREG|SCON, TLL, + SCREG|SNAME|SOREG|SCON, TLL, + NSPECIAL|NCREG|NCSL|NCSR, RESC1, + "ZO", }, + +{ DIV, INAREG, + SAREG, TSWORD, + SAREG|SNAME|SOREG, TWORD, + NSPECIAL, RDEST, + " cltd\n idivl AR\n", }, + +{ DIV, INAREG, + SAREG, TUWORD|TPOINT, + SAREG|SNAME|SOREG, TUWORD|TPOINT, + NSPECIAL, RDEST, + " xorl %edx,%edx\n divl AR\n", }, + +{ DIV, INAREG, + SAREG, TUSHORT, + SAREG|SNAME|SOREG, TUSHORT, + NSPECIAL, RDEST, + " xorl %edx,%edx\n divw AR\n", }, + +{ DIV, INCH, + SHCH, TUCHAR, + SHCH|SNAME|SOREG, TUCHAR, + NSPECIAL, RDEST, + " xorb %ah,%ah\n divb AR\n", }, + +{ DIV, INFL, + SHFL, TDOUBLE, + SNAME|SOREG, TDOUBLE, + 0, RLEFT, + " fdivl AR\n", }, + +{ DIV, INFL, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + 0, RLEFT, + " fdivZAp\n", }, + +/* (u)longlong mod is emulated */ +{ MOD, INCREG, + SCREG|SNAME|SOREG|SCON, TLL, + SCREG|SNAME|SOREG|SCON, TLL, + NSPECIAL|NCREG|NCSL|NCSR, RESC1, + "ZO", }, + +{ MOD, INAREG, + SAREG, TSWORD, + SAREG|SNAME|SOREG, TSWORD, + NAREG|NSPECIAL, RESC1, + " cltd\n idivl AR\n", }, + +{ MOD, INAREG, + SAREG, TUWORD|TPOINT, + SAREG|SNAME|SOREG, TUWORD|TPOINT, + NAREG|NSPECIAL, RESC1, + " xorl %edx,%edx\n divl AR\n", }, + +{ MOD, INAREG, + SAREG, TUSHORT, + SAREG|SNAME|SOREG, TUSHORT, + NAREG|NSPECIAL, RESC1, + " xorl %edx,%edx\n divw AR\n", }, + +{ MOD, INCH, + SHCH, TUCHAR, + SHCH|SNAME|SOREG, TUCHAR, + NBREG|NSPECIAL, RESC1, + " xorb %ah,%ah\n divb AR\n", }, + +/* (u)longlong mul is emulated */ +{ MUL, INCREG, + SCREG|SNAME|SOREG|SCON, TLL, + SCREG|SNAME|SOREG|SCON, TLL, + NSPECIAL|NCREG|NCSL|NCSR, RESC1, + "ZO", }, + +{ MUL, INAREG, + SAREG, TWORD|TPOINT, + SAREG|SNAME|SOREG|SCON, TWORD|TPOINT, + 0, RLEFT, + " imull AR,AL\n", }, + +{ MUL, INAREG, + SAREG, TSHORT|TUSHORT, + SAREG|SNAME|SOREG, TSHORT|TUSHORT, + 0, RLEFT, + " imulw AR,AL\n", }, + +{ MUL, INCH, + SHCH, TCHAR|TUCHAR, + SHCH|SNAME|SOREG, TCHAR|TUCHAR, + NSPECIAL, RDEST, + " imulb AR\n", }, + +{ MUL, INFL, + SHFL, TDOUBLE, + SNAME|SOREG, TDOUBLE, + 0, RLEFT, + " fmull AR\n", }, + +{ MUL, INFL, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + 0, RLEFT, + " fmulp\n", }, + +/* + * Indirection operators. + */ +{ UMUL, INLL, + SANY, TANY, + SOREG, TLL, + NCREG|NCSL, RESC1, + " movl UL,U1\n movl AL,A1\n", }, + +{ UMUL, INAREG, + SANY, TPOINT|TWORD, + SOREG, TPOINT|TWORD, + NAREG|NASL, RESC1, + " movl AL,A1\n", }, + +{ UMUL, INCH, + SANY, TANY, + SOREG, TCHAR|TUCHAR, + NBREG|NBSL, RESC1, + " movb AL,A1\n", }, + +{ UMUL, INAREG, + SANY, TANY, + SOREG, TSHORT|TUSHORT, + NAREG|NASL, RESC1, + " movw AL,A1\n", }, + +{ UMUL, INFL, + SANY, TANY, + SOREG, TLDOUBLE, + NDREG|NDSL, RESC1, + " fldt AL\n", }, + +{ UMUL, INFL, + SANY, TANY, + SOREG, TDOUBLE, + NDREG|NDSL, RESC1, + " fldl AL\n", }, + +{ UMUL, INFL, + SANY, TANY, + SOREG, TFLOAT, + NDREG|NDSL, RESC1, + " flds AL\n", }, + +/* + * Logical/branching operators + */ + +/* Comparisions, take care of everything */ +{ OPLOG, FORCC, + SHLL|SOREG|SNAME, TLL, + SHLL, TLL, + 0, 0, + "ZD", }, + +{ OPLOG, FORCC, + SAREG|SOREG|SNAME, TWORD|TPOINT, + SCON|SAREG, TWORD|TPOINT, + 0, RESCC, + " cmpl AR,AL\n", }, + +{ OPLOG, FORCC, + SCON|SAREG, TWORD|TPOINT, + SAREG|SOREG|SNAME, TWORD|TPOINT, + 0, RESCC, + " cmpl AR,AL\n", }, + +{ OPLOG, FORCC, + SAREG|SOREG|SNAME, TSHORT|TUSHORT, + SCON|SAREG, TANY, + 0, RESCC, + " cmpw AR,AL\n", }, + +{ OPLOG, FORCC, + SBREG|SOREG|SNAME, TCHAR|TUCHAR, + SCON|SBREG, TANY, + 0, RESCC, + " cmpb AR,AL\n", }, + +{ OPLOG, FORCC, + SDREG, TLDOUBLE|TDOUBLE|TFLOAT, + SDREG, TLDOUBLE|TDOUBLE|TFLOAT, + NSPECIAL, 0, + "ZG", }, + +{ OPLOG, FORCC, + SOREG|SNAME, TDOUBLE|TFLOAT, + SDREG, TLDOUBLE|TDOUBLE|TFLOAT, + NSPECIAL, 0, + "ZG", }, + +#if 0 +/* Ppro and later only */ +{ OPLOG, FORCC, + SDREG, TLDOUBLE|TDOUBLE|TFLOAT, + SDREG, TLDOUBLE|TDOUBLE|TFLOAT, + 0, RESCC, + "ZA fucomip %st,%st(1)\n", }, +#endif + +{ OPLOG, FORCC, + SANY, TANY, + SANY, TANY, + REWRITE, 0, + "diediedie!", }, + +/* AND/OR/ER/NOT */ +{ AND, INAREG|FOREFF, + SAREG|SOREG|SNAME, TWORD, + SCON|SAREG, TWORD, + 0, RLEFT, + " andl AR,AL\n", }, + +{ AND, INCREG|FOREFF, + SCREG, TLL, + SCREG|SOREG|SNAME, TLL, + 0, RLEFT, + " andl AR,AL\n andl UR,UL\n", }, + +{ AND, INAREG|FOREFF, + SAREG, TWORD, + SAREG|SOREG|SNAME, TWORD, + 0, RLEFT, + " andl AR,AL\n", }, + +{ AND, INAREG|FOREFF, + SAREG|SOREG|SNAME, TSHORT|TUSHORT, + SCON|SAREG, TSHORT|TUSHORT, + 0, RLEFT, + " andw AR,AL\n", }, + +{ AND, INAREG|FOREFF, + SAREG, TSHORT|TUSHORT, + SAREG|SOREG|SNAME, TSHORT|TUSHORT, + 0, RLEFT, + " andw AR,AL\n", }, + +{ AND, INBREG|FOREFF, + SBREG|SOREG|SNAME, TCHAR|TUCHAR, + SCON|SBREG, TCHAR|TUCHAR, + 0, RLEFT, + " andb AR,AL\n", }, + +{ AND, INBREG|FOREFF, + SBREG, TCHAR|TUCHAR, + SBREG|SOREG|SNAME, TCHAR|TUCHAR, + 0, RLEFT, + " andb AR,AL\n", }, +/* AND/OR/ER/NOT */ + +/* + * Jumps. + */ +{ GOTO, FOREFF, + SCON, TANY, + SANY, TANY, + 0, RNOP, + " jmp LL\n", }, + +#ifdef GCC_COMPAT +{ GOTO, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, RNOP, + " jmp *AL\n", }, +#endif + +/* + * Convert LTYPE to reg. + */ +{ OPLTYPE, INLL, + SANY, TANY, + SCREG|SCON|SOREG|SNAME, TLL, + NCREG, RESC1, + " movl UL,U1\n movl AL,A1\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SAREG|SCON|SOREG|SNAME, TWORD|TPOINT, + NAREG|NASL, RESC1, + " movl AL,A1\n", }, + +{ OPLTYPE, INBREG, + SANY, TANY, + SBREG|SOREG|SNAME|SCON, TCHAR|TUCHAR, + NBREG, RESC1, + " movb AL,A1\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SAREG|SOREG|SNAME|SCON, TSHORT|TUSHORT, + NAREG, RESC1, + " movw AL,A1\n", }, + +{ OPLTYPE, INDREG, + SANY, TLDOUBLE, + SOREG|SNAME, TLDOUBLE, + NDREG, RESC1, + " fldt AL\n", }, + +{ OPLTYPE, INDREG, + SANY, TDOUBLE, + SOREG|SNAME, TDOUBLE, + NDREG, RESC1, + " fldl AL\n", }, + +{ OPLTYPE, INDREG, + SANY, TFLOAT, + SOREG|SNAME, TFLOAT, + NDREG, RESC1, + " flds AL\n", }, + +/* Only used in ?: constructs. The stack already contains correct value */ +{ OPLTYPE, INDREG, + SANY, TFLOAT|TDOUBLE|TLDOUBLE, + SDREG, TFLOAT|TDOUBLE|TLDOUBLE, + NDREG, RESC1, + "", }, + +/* + * Negate a word. + */ + +{ UMINUS, INCREG|FOREFF, + SCREG, TLL, + SCREG, TLL, + 0, RLEFT, + " negl AL\n adcl $0,UL\n negl UL\n", }, + +{ UMINUS, INAREG|FOREFF, + SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + 0, RLEFT, + " negl AL\n", }, + +{ UMINUS, INAREG|FOREFF, + SAREG, TSHORT|TUSHORT, + SAREG, TSHORT|TUSHORT, + 0, RLEFT, + " negw AL\n", }, + +{ UMINUS, INBREG|FOREFF, + SBREG, TCHAR|TUCHAR, + SBREG, TCHAR|TUCHAR, + 0, RLEFT, + " negb AL\n", }, + +{ UMINUS, INFL|FOREFF, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + SHFL, TLDOUBLE|TDOUBLE|TFLOAT, + 0, RLEFT, + " fchs\n", }, + +{ COMPL, INCREG, + SCREG, TLL, + SANY, TANY, + 0, RLEFT, + " notl AL\n notl UL\n", }, + +{ COMPL, INAREG, + SAREG, TWORD, + SANY, TANY, + 0, RLEFT, + " notl AL\n", }, + +{ COMPL, INAREG, + SAREG, TSHORT|TUSHORT, + SANY, TANY, + 0, RLEFT, + " notw AL\n", }, + +{ COMPL, INBREG, + SBREG, TCHAR|TUCHAR, + SANY, TANY, + 0, RLEFT, + " notb AL\n", }, + +/* + * Arguments to functions. + */ +{ FUNARG, FOREFF, + SCON|SCREG|SNAME|SOREG, TLL, + SANY, TLL, + 0, RNULL, + " pushl UL\n pushl AL\n", }, + +{ FUNARG, FOREFF, + SCON|SAREG|SNAME|SOREG, TWORD|TPOINT, + SANY, TWORD|TPOINT, + 0, RNULL, + " pushl AL\n", }, + +{ FUNARG, FOREFF, + SCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SANY, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + 0, RNULL, + " pushl AL\n", }, + +{ FUNARG, FOREFF, + SAREG|SNAME|SOREG, TSHORT, + SANY, TSHORT, + NAREG, 0, + " movswl AL,ZN\n pushl ZN\n", }, + +{ FUNARG, FOREFF, + SAREG|SNAME|SOREG, TUSHORT, + SANY, TUSHORT, + NAREG, 0, + " movzwl AL,ZN\n pushl ZN\n", }, + +{ FUNARG, FOREFF, + SHCH|SNAME|SOREG, TCHAR, + SANY, TCHAR, + NAREG, 0, + " movsbl AL,A1\n pushl A1\n", }, + +{ FUNARG, FOREFF, + SHCH|SNAME|SOREG, TUCHAR, + SANY, TUCHAR, + NAREG, 0, + " movzbl AL,A1\n pushl A1\n", }, + +{ FUNARG, FOREFF, + SNAME|SOREG, TDOUBLE, + SANY, TDOUBLE, + 0, 0, + " pushl UL\n pushl AL\n", }, + +{ FUNARG, FOREFF, + SDREG, TDOUBLE, + SANY, TDOUBLE, + 0, 0, + " subl $8,%esp\n fstpl (%esp)\n", }, + +{ FUNARG, FOREFF, + SNAME|SOREG, TFLOAT, + SANY, TFLOAT, + 0, 0, + " pushl AL\n", }, + +{ FUNARG, FOREFF, + SDREG, TFLOAT, + SANY, TFLOAT, + 0, 0, + " subl $4,%esp\n fstps (%esp)\n", }, + +{ FUNARG, FOREFF, + SDREG, TLDOUBLE, + SANY, TLDOUBLE, + 0, 0, + " subl $12,%esp\n fstpt (%esp)\n", }, + +{ STARG, FOREFF, + SAREG|SOREG|SNAME|SCON, TANY, + SANY, TSTRUCT, + NSPECIAL|NAREG, 0, + "ZF", }, + +#endif + +# define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,"" + +{ UMUL, DF( UMUL ), }, + +{ ASSIGN, DF(ASSIGN), }, + +{ STASG, DF(STASG), }, + +{ FLD, DF(FLD), }, + +{ OPLEAF, DF(NAME), }, + +{ INIT, DF(INIT), }, + +{ OPUNARY, DF(UMINUS), }, + +{ OPANY, DF(BITYPE), }, + +{ FREE, FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" }, +}; + +int tablesize = sizeof(table)/sizeof(table[0]); diff --git a/compilers/pcc/pcc-1.0.0/arch/pdp10/CVS/Entries b/compilers/pcc/pcc-1.0.0/arch/pdp10/CVS/Entries new file mode 100644 index 00000000..30d83cb2 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/pdp10/CVS/Entries @@ -0,0 +1,8 @@ +/README/1.1/Mon Nov 12 19:00:04 2007//Tr-1-0-0-RELEASE +/code.c/1.39/Tue Jul 29 13:25:58 2008//Tr-1-0-0-RELEASE +/local.c/1.72/Fri Jan 21 21:47:58 2011//Tr-1-0-0-RELEASE +/local2.c/1.102/Sat Nov 22 16:12:25 2008//Tr-1-0-0-RELEASE +/macdefs.h/1.30/Sat Jan 24 21:43:49 2009//Tr-1-0-0-RELEASE +/order.c/1.63/Tue Jan 15 21:47:06 2008//Tr-1-0-0-RELEASE +/table.c/1.97/Sun Feb 10 19:25:44 2008//Tr-1-0-0-RELEASE +D diff --git a/compilers/pcc/pcc-1.0.0/arch/pdp10/CVS/Repository b/compilers/pcc/pcc-1.0.0/arch/pdp10/CVS/Repository new file mode 100644 index 00000000..314cad0d --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/pdp10/CVS/Repository @@ -0,0 +1 @@ +pcc/arch/pdp10 diff --git a/compilers/pcc/pcc-1.0.0/arch/pdp10/CVS/Root b/compilers/pcc/pcc-1.0.0/arch/pdp10/CVS/Root new file mode 100644 index 00000000..71e2ccb9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/pdp10/CVS/Root @@ -0,0 +1 @@ +/cvsroot diff --git a/compilers/pcc/pcc-1.0.0/arch/pdp10/CVS/Tag b/compilers/pcc/pcc-1.0.0/arch/pdp10/CVS/Tag new file mode 100644 index 00000000..060fac05 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/pdp10/CVS/Tag @@ -0,0 +1 @@ +Nr-1-0-0-RELEASE diff --git a/compilers/pcc/pcc-1.0.0/arch/pdp10/README b/compilers/pcc/pcc-1.0.0/arch/pdp10/README new file mode 100644 index 00000000..176eca77 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/pdp10/README @@ -0,0 +1,20 @@ + + +PDP10 C calling convention +-------------------------- +Register 1-7 are argument registers. Types of sizes up to 36 bits are +given in one register, two otherwise. CHAR and SHORT are given as INTs. + +If the argument that would end up in register 7 requires two registers, +it is saved on the stack instead and no more registers would end up +on the stack. + +struct return: a hidden argument containing the address of the struct +is stored as the first argument _on_the_stack_, never in register. + +struct argument: always saved on stack, and terminates the list +of arguments that are kept in registers. + +In case of debugging all arguments are saved on stack in the function. + +All variadic arguments are always saved on the stack. diff --git a/compilers/pcc/pcc-1.0.0/arch/pdp10/code.c b/compilers/pcc/pcc-1.0.0/arch/pdp10/code.c new file mode 100644 index 00000000..35bc75da --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/pdp10/code.c @@ -0,0 +1,223 @@ +/* $Id: code.c,v 1.39 2008/07/29 13:25:58 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass1.h" + +/* + * Define everything needed to print out some data (or text). + * This means segment, alignment, visibility, etc. + */ +void +defloc(struct symtab *sp) +{ + char *nextsect = NULL; /* notyet */ + static char *loctbl[] = { "text", "data", "section .rodata" }; + static int lastloc = -1; + TWORD t; + int s; + + if (sp == NULL) { + lastloc = -1; + return; + } + t = sp->stype; + s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA; + if (nextsect) { + printf(" .section %s\n", nextsect); + nextsect = NULL; + s = -1; + } else if (s != lastloc) + printf(" .%s\n", loctbl[s]); + lastloc = s; + if (sp->sclass == EXTDEF) + printf(" .globl %s\n", sp->soname); + if (sp->slevel == 0) + printf("%s:\n", sp->soname); + else + printf(LABFMT ":\n", sp->soffset); +} + +/* + * code for the end of a function + */ +void +efcode() +{ +} + +/* + * code for the beginning of a function; a is an array of + * indices in stab for the arguments; n is the number + */ +void +bfcode(struct symtab **sp, int cnt) +{ + NODE *p, *q; + int i, n; + + if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) { + uerror("no struct return yet"); + } + /* recalculate the arg offset and create TEMP moves */ + for (n = 1, i = 0; i < cnt; i++) { + if (n < 8) { + p = tempnode(0, sp[i]->stype, sp[i]->sdf, sp[i]->ssue); + q = block(REG, NIL, NIL, + sp[i]->stype, sp[i]->sdf, sp[i]->ssue); + q->n_rval = n; + p = buildtree(ASSIGN, p, q); + sp[i]->soffset = regno(p->n_left); + sp[i]->sflags |= STNODE; + ecomp(p); + } else { + sp[i]->soffset += SZINT * n; + if (xtemps) { + /* put stack args in temps if optimizing */ + p = tempnode(0, sp[i]->stype, + sp[i]->sdf, sp[i]->ssue); + p = buildtree(ASSIGN, p, nametree(sp[i])); + sp[i]->soffset = regno(p->n_left); + sp[i]->sflags |= STNODE; + ecomp(p); + } + } + n += szty(sp[i]->stype); + } +} + + +/* + * by now, the automatics and register variables are allocated + */ +void +bccode() +{ + SETOFF(autooff, SZINT); +} + +void +bjobcode() +{ +} + +/* called just before final exit */ +/* flag is 1 if errors, 0 if none */ +void +ejobcode(int flag ) +{ +} + +/* + * Make a register node, helper for funcode. + */ +static NODE * +mkreg(NODE *p, int n) +{ + NODE *r; + + r = block(REG, NIL, NIL, p->n_type, p->n_df, p->n_sue); + if (szty(p->n_type) == 2) + n += 16; + r->n_rval = n; + return r; +} + +static int regnum; +/* + * Move args to registers and emit expressions bottom-up. + */ +static void +fixargs(NODE *p) +{ + NODE *r; + + if (p->n_op == CM) { + fixargs(p->n_left); + r = p->n_right; + if (r->n_op == STARG) + regnum = 9; /* end of register list */ + else if (regnum + szty(r->n_type) > 8) + p->n_right = block(FUNARG, r, NIL, r->n_type, + r->n_df, r->n_sue); + else + p->n_right = buildtree(ASSIGN, mkreg(r, regnum), r); + } else { + if (p->n_op == STARG) { + regnum = 9; /* end of register list */ + } else { + r = talloc(); + *r = *p; + r = buildtree(ASSIGN, mkreg(r, regnum), r); + *p = *r; + nfree(r); + } + r = p; + } + regnum += szty(r->n_type); +} + + +/* + * Called with a function call with arguments as argument. + * This is done early in buildtree() and only done once. + */ +NODE * +funcode(NODE *p) +{ + + regnum = 1; + + fixargs(p->n_right); + return p; +} + +/* + * return the alignment of field of type t + */ +int +fldal(unsigned int t) +{ + uerror("illegal field type"); + return(ALINT); +} + +/* fix up type of field p */ +void +fldty(struct symtab *p) +{ +} + +/* + * XXX - fix genswitch. + */ +int +mygenswitch(int num, TWORD type, struct swents **p, int n) +{ + return 0; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/pdp10/local.c b/compilers/pcc/pcc-1.0.0/arch/pdp10/local.c new file mode 100644 index 00000000..d816a6a1 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/pdp10/local.c @@ -0,0 +1,878 @@ +/* $Id: local.c,v 1.72 2011/01/21 21:47:58 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass1.h" + +/* this file contains code which is dependent on the target machine */ + +static int pointp(TWORD t); +static struct symtab *newfun(char *name, TWORD type); + +#define PTRNORMAL 1 +#define PTRCHAR 2 +#define PTRSHORT 3 +static int xptype(TWORD t); + +NODE * +clocal(NODE *p) +{ + /* this is called to do local transformations on + an expression tree preparitory to its being + written out in intermediate code. + */ + + /* the major essential job is rewriting the + automatic variables and arguments in terms of + REG and OREG nodes */ + /* conversion ops which are not necessary are also clobbered here */ + /* in addition, any special features (such as rewriting + exclusive or) are easily handled here as well */ + + register struct symtab *q; + register NODE *r, *l, *oop; + register int o; + register int m, ml; + int siz; + +#ifdef PCC_DEBUG + if (xdebug) { + printf("clocal: %p\n", p); + fwalk(p, eprint, 0); + } +#endif + + switch( o = p->n_op ){ + + case NAME: + if ((q = p->n_sp) == NULL) + return p; /* Nothing to care about */ + + switch (q->sclass) { + + case PARAM: + /* First 7 parameters are in registers */ + /* XXX last may be double */ + if (q->soffset/SZINT < 7) { + p->n_op = REG; + p->n_rval = q->soffset/SZINT; + break; + } else + q->soffset -= 7*SZINT; + + case AUTO: + /* fake up a structure reference */ + if (q->stype == CHAR || q->stype == UCHAR || + q->stype == SHORT || q->stype == USHORT) + r = block(REG, NIL, NIL, PTR+q->stype, 0, 0); + else + r = block(REG, NIL, NIL, PTR+STRTY, 0, 0); + r->n_lval = 0; + r->n_rval = FPREG; + p = stref(block(STREF, r, p, 0, 0, 0)); + break; + + case STATIC: + if (q->slevel == 0) + break; + p->n_lval = 0; + break; + + case REGISTER: + p->n_op = REG; + p->n_lval = 0; + p->n_rval = q->soffset; + break; + + } + break; + + case CALL: + /* avoid recursive calls */ + r = tempnode(0, p->n_type, p->n_df, p->n_sue); + l = tempnode(regno(r), p->n_type, p->n_df, p->n_sue); + ecomp(buildtree(ASSIGN, r, p)); + p = l; + break; + + case PCONV: + l = p->n_left; + /* + * Handle frame pointer directly without conversion, + * for efficiency. + */ + if (l->n_op == REG && l->n_rval == 0) { +rmpc: l->n_type = p->n_type; + l->n_df = p->n_df; + l->n_sue = p->n_sue; + nfree(p); + return l; + } + /* Convert ICON with name to new type */ + if (l->n_op == ICON && l->n_sp != NULL && + l->n_type == INCREF(STRTY) && + (p->n_type == INCREF(CHAR) || + p->n_type == INCREF(UCHAR) || + p->n_type == INCREF(SHORT) || + p->n_type == INCREF(USHORT))) { + l->n_lval *= (BTYPE(p->n_type) == CHAR || + BTYPE(p->n_type) == UCHAR ? 4 : 2); + goto rmpc; + } + /* Convert only address constants, never convert other */ + if (l->n_op == ICON) { + if (l->n_sp == NULL) + goto rmpc; + if (p->n_type == INCREF(CHAR) || + p->n_type == INCREF(UCHAR) || + p->n_type == INCREF(VOID)) + l->n_lval = (l->n_lval & 07777777777) | + 0700000000000LL; + else if (p->n_type == INCREF(SHORT) || + p->n_type == INCREF(USHORT)) + l->n_lval = (l->n_lval & 07777777777) | + 0750000000000LL; + else + l->n_lval = l->n_lval & 07777777777; + goto rmpc; + } + + /* Remove more conversions of identical pointers */ + /* Be careful! optim() may do bad things */ + if (ISPTR(DECREF(p->n_type))) { + if (ISPTR(DECREF(l->n_type))) { + if ((coptype(l->n_op) == UTYPE || + coptype(l->n_op) == BITYPE) && + (l->n_left->n_op == REG)) + l->n_left->n_type = p->n_type; + goto rmpc; + } + } + + /* Change PCONV from int to double pointer to right shift */ + if (ISPTR(p->n_type) && ISPTR(DECREF(p->n_type)) && + (l->n_type == INT || l->n_type == UNSIGNED)) { + p->n_op = RS; + p->n_right = bcon(2); + break; + } + + /* Check for cast integral -> pointer */ + if (BTYPE(l->n_type) == l->n_type) + break; + + /* Remove conversions to identical pointers */ + switch (xptype(p->n_type)) { + case PTRNORMAL: + if (xptype(l->n_type) == PTRNORMAL) + goto rmpc; + break; + + case PTRSHORT: + if (xptype(l->n_type) == PTRSHORT) + goto rmpc; + break; + + case PTRCHAR: + if (xptype(l->n_type) == PTRCHAR) + goto rmpc; + break; + } + + break; + + case SCONV: + l = p->n_left; + + if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 && + btdims[p->n_type].suesize == btdims[l->n_type].suesize) { + if (p->n_type != FLOAT && p->n_type != DOUBLE && + l->n_type != FLOAT && l->n_type != DOUBLE) { + nfree(p); + return l; + } + } + /* cast to (void) XXX should be removed in MI code */ + if (p->n_type == VOID) { + nfree(p); + return l; + } + m = p->n_type; + ml = l->n_type; + if (m == ml) { + nfree(p); + return l; + } + o = l->n_op; + if (ml == FLOAT || ml == DOUBLE) { + if (o != FCON) + break; + ml = ISUNSIGNED(m) ? UNSIGNED : INT; /* LONG? */ + r = xbcon(ml == INT ? (int)p->n_left->n_dcon : + (unsigned)p->n_left->n_dcon, + NULL, ml); + nfree(p->n_left); + p->n_left = r; + o = ICON; + if (m == ml) { + r = p->n_left; + nfree(p); + return r; + } + } + if (o == ICON) { + CONSZ val = l->n_lval; + + switch (m) { + case CHAR: + l->n_lval = val & 0777; + if (val & 0400) + l->n_lval |= ~((CONSZ)0777); + break; + case UCHAR: + l->n_lval = val & 0777; + break; + case USHORT: + l->n_lval = val & 0777777; + break; + case SHORT: + l->n_lval = val & 0777777; + if (val & 0400000) + l->n_lval |= ~((CONSZ)0777777); + break; + case UNSIGNED: + l->n_lval = val & 0777777777777LL; + break; + case INT: + l->n_lval = val & 0777777777777LL; + if (val & 0400000000000LL) + l->n_lval |= ~(0777777777777LL); + break; + case LONGLONG: /* XXX */ + case ULONGLONG: + l->n_lval = val; + break; + case VOID: + break; + case DOUBLE: + case FLOAT: + l->n_op = FCON; + l->n_dcon = 0; + break; + default: + cerror("unknown type %d", m); + } + l->n_type = m; + l->n_sue = MKSUE(m); + nfree(p); + return l; + } + break; + + case PMCONV: + case PVCONV: +/* if( p->n_right->n_op != ICON ) cerror( "bad conversion", 0); */ + nfree(p); + return(buildtree(o==PMCONV?MUL:DIV, p->n_left, p->n_right)); + + case RS: + case RSEQ: + /* convert >> to << with negative shift count */ + /* Beware! constant shifts will be converted back in optim() */ + + if (p->n_right->n_op != UMINUS) { + p->n_right = buildtree(UMINUS, p->n_right, NIL); + } else { + r = p->n_right; + p->n_right = p->n_right->n_left; + nfree(r); + } + if (p->n_op == RS) + p->n_op = LS; + else + p->n_op = LSEQ; + break; + + case UMUL: /* Convert structure assignment to memcpy() */ + if (p->n_left->n_op == PLUS && + p->n_left->n_left->n_op == PCONV && + p->n_left->n_right->n_op == ICON && + (p->n_type == CHAR || p->n_type == UCHAR || + p->n_type == SHORT || p->n_type == USHORT)) { + /* Can remove the left SCONV */ + l = p->n_left->n_left; + p->n_left->n_left = l->n_left; + nfree(l); + break; + + } + if (p->n_left->n_op != STASG) + break; + oop = p; + p = p->n_left; + siz = p->n_sue->suesize/SZCHAR; + l = p->n_left; + r = p->n_right; + if (l->n_type == STRTY || l->n_type == UNIONTY) { + if (l->n_op == UMUL) { + p->n_left = l->n_left; + nfree(l); + l = p->n_left; + } else { + l = block(ADDROF, l, NIL, INCREF(l->n_type), + 0, MKSUE(INT)); + } + } + if ((l->n_type != (STRTY+PTR) && l->n_type != (UNIONTY+PTR)) || + (r->n_type != (STRTY+PTR) && r->n_type != (UNIONTY+PTR))) + cerror("bad stasg, l = %o, r = %o", l->n_type, r->n_type); + q = newfun("__structcpy", p->n_type); + + /* structure pointer block */ + l = block(CM, l, r, INT, 0, MKSUE(INT)); + /* Size block */ + r = block(CM, l, bcon(siz), INT, 0, MKSUE(INT)); + + l = xbcon(0, q, q->stype); + p->n_left = l; + p->n_right = r; + p->n_op = CALL; + oop->n_left = p; + return oop; + + case FORCE: + p->n_op = ASSIGN; + p->n_right = p->n_left; + p->n_left = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT)); + p->n_left->n_rval = RETREG(p->n_type); + break; + + } + + return(p); +} + +void +myp2tree(NODE *p) +{ + NODE *r; + + switch (p->n_op) { + case ULT: /* exor sign bit to avoid unsigned comparitions */ + case ULE: + case UGT: + case UGE: + if (ISLONGLONG(p->n_left->n_type)) { + /* XXX */ + r = xbcon(0x8000000000000000ULL, NULL, LONGLONG); + } else + r = xbcon(0400000000000LL, NULL, INT); + p->n_left = buildtree(ER, p->n_left, r); + if (ISUNSIGNED(p->n_left->n_type)) + p->n_left->n_type = DEUNSIGN(p->n_left->n_type); + + if (ISLONGLONG(p->n_right->n_type)) { + /* XXX */ + r = xbcon(0x8000000000000000ULL, NULL, LONGLONG); + } else + r = xbcon(0400000000000LL, NULL, INT); + p->n_right = buildtree(ER, p->n_right, r); + if (ISUNSIGNED(p->n_right->n_type)) + p->n_right->n_type = DEUNSIGN(p->n_right->n_type); + + p->n_op -= (ULT-LT); + break; + case FCON: + cerror("fix float constants"); + } +} + + +struct symtab * +newfun(char *name, TWORD type) +{ + struct symtab *sp; + + sp = lookup(name, 0); + if (sp->stype == VOID) { + sp->stype = INCREF(type | FTN); + sp->sclass = EXTERN; + sp->soffset = 0; + } +#ifdef notdef + else if (!ISFTN(DECREF(sp->stype))) + uerror("reserved name '%s' used illegally", name); +#endif + return sp; +} + +/*ARGSUSED*/ +int +andable(NODE *p) +{ + return(1); /* all names can have & taken on them */ +} + +/* + * at the end of the arguments of a ftn, set the automatic offset + */ +void +cendarg() +{ + autooff = AUTOINIT; +} + +/* + * is an automatic variable of type t OK for a register variable + * Everything is trusted to be in register here. + */ +int +cisreg(TWORD t) +{ + return(1); +} + +int +xptype(TWORD t) +{ + int tt = BTYPE(t); + int e, rv; + + if (!ISPTR(t)) + cerror("not a pointer"); + + e = t & ~BTMASK; + rv = e; + while (e) { + rv = e; + if (DECREF(e) == 0) + break; + e = DECREF(e); + } + if (ISFTN(rv)) + return PTRNORMAL; + + switch (tt) { + case INT: + case LONG: + case LONGLONG: + case FLOAT: + case DOUBLE: + case STRTY: + case UNIONTY: + case UNSIGNED: + case ULONG: + case ULONGLONG: + return PTRNORMAL; + case VOID: + case CHAR: + case UCHAR: + if (DECREF(t) == tt || ISARY(rv)) + return PTRCHAR; + return PTRNORMAL; + case SHORT: + case USHORT: + if (DECREF(t) == tt || ISARY(rv)) + return PTRSHORT; + return PTRNORMAL; + default: + break; + } + cerror("unknown type"); + return PTRNORMAL; /* XXX */ +} + +/* + * Help routine to the one below; return true if it's not a word pointer. + */ +static int +pointp(TWORD t) +{ + int rv = 0; + + if (ISPTR(t) && ((t & TMASK1) == 0)) + return 1; + + t &= ~BTMASK; + while (t) { + rv = ISARY(t); + t = DECREF(t); + } + return rv; +} + +/* + * return a node, for structure references, which is suitable for + * being added to a pointer of type t, in order to be off bits offset + * into a structure + * t, d, and s are the type, dimension offset, and sizeoffset + * For pdp10, return the type-specific index number which calculation + * is based on its size. For example, short a[3] would return 3. + * Be careful about only handling first-level pointers, the following + * indirections must be fullword. + */ +NODE * +offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue) +{ + register NODE *p; + + if (xdebug) + printf("offcon: OFFSZ %lld type %x dim %p siz %d\n", + off, t, d, sue->suesize); + + p = bcon(0); + p->n_lval = off/SZINT; /* Default */ + if (ISPTR(DECREF(t))) + return p; /* Pointer/pointer reference */ + switch (BTMASK & t) { + case INT: + case UNSIGNED: + case LONG: + case ULONG: + case STRTY: + case UNIONTY: + case LONGLONG: + case ULONGLONG: + case FLOAT: + case DOUBLE: + break; + + case SHORT: + case USHORT: + if (pointp(t)) + p->n_lval = off/SZSHORT; + break; + + case VOID: /* void pointers */ + case CHAR: + case UCHAR: + if (pointp(t)) + p->n_lval = off/SZCHAR; + break; + + default: + cerror("offcon, off %llo size %d type %x", off, sue->suesize, t); + } + if (xdebug) + printf("offcon return 0%llo\n", p->n_lval); + return(p); +} + +/* + * Allocate off bits on the stack. p is a tree that when evaluated + * is the multiply count for off, t is a NAME node where to write + * the allocated address. + * Be aware that a pointer conversion may be needed when saving + * to node t! + */ +void +spalloc(NODE *t, NODE *p, OFFSZ off) +{ + NODE *sp; + + if ((off % SZINT) == 0) + p = buildtree(MUL, p, bcon(off/SZINT)); + else if ((off % SZSHORT) == 0) { + p = buildtree(MUL, p, bcon(off/SZSHORT)); + p = buildtree(PLUS, p, bcon(1)); + p = buildtree(RS, p, bcon(1)); + } else if ((off % SZCHAR) == 0) { + p = buildtree(MUL, p, bcon(off/SZCHAR)); + p = buildtree(PLUS, p, bcon(3)); + p = buildtree(RS, p, bcon(2)); + } else + cerror("roundsp"); + + /* save the address of sp */ + sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_sue); + sp->n_lval = 0; + sp->n_rval = STKREG; + /* Cast sp to destination type (may be redundant) */ + sp = buildtree(CAST, + block(NAME, NIL, NIL, t->n_type, t->n_df, t->n_sue), sp); + nfree(sp->n_left); + nfree(sp); + sp = sp->n_right; + ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */ + + /* add the size to sp */ + sp = block(REG, NIL, NIL, p->n_type, 0, 0); + sp->n_lval = 0; + sp->n_rval = STKREG; + ecomp(buildtree(PLUSEQ, sp, p)); +} + +#if 0 +static int inwd; /* current bit offsed in word */ +static CONSZ word; /* word being built from fields */ + +/* + * Generate initialization code for assigning a constant c + * to a field of width sz + * we assume that the proper alignment has been obtained + * inoff is updated to have the proper final value + * we also assume sz < SZINT + */ +void +incode(NODE *p, int sz) +{ + char *s; + + inoff += sz; + if ((sz + inwd) > SZINT) + cerror("incode: field > int"); + + word |= ((p->n_lval & ((1 << sz) - 1)) << (36 - inwd - sz)); + + inwd += sz; + if (inoff % SZINT == 0) { + s = isinlining ? permalloc(30) : tmpalloc(30); + sprintf(s, " .long 0%llo", word); + send_passt(IP_ASM, s); + word = inwd = 0; + } + tfree(p); +} + +/* output code to initialize space of size sz to the value d */ +/* the proper alignment has been obtained */ +/* inoff is updated to have the proper final value */ +/* on the target machine, write it out in octal! */ +void +fincode(NODE *p, int sz) +{ + double d = p->n_dcon; + + if(!nerrors) + printf(" %s 0%c%.20e\n", + sz == SZDOUBLE ? ".double" : ".float", + sz == SZDOUBLE ? 'd' : 'f', d); + inoff += sz; +} + +void +cinit(NODE *p, int sz) +{ + NODE *l; + + /* + * as a favor (?) to people who want to write + * int i = 9600/134.5; + * we will, under the proper circumstances, do + * a coercion here. + */ + switch (p->n_type) { + case INT: + case UNSIGNED: + l = p->n_left; + if (l->n_op != SCONV || l->n_left->n_op != FCON) + break; + nfree(l); + l = l->n_left; + l->n_lval = (long)(l->n_dcon); + l->n_sp = NULL; + l->n_op = ICON; + l->n_type = INT; + p->n_left = l; + break; + } + /* arrange for the initialization of p into a space of size sz */ + /* the proper alignment has been opbtained */ + /* inoff is updated to have the proper final value */ + ecode( p ); + inoff += sz; +} + +/* + * define n bits of zeros in a vfd + */ +void +vfdzero(int n) +{ + char *s; + + inoff += n; + inwd += n; + if (inoff%ALINT ==0) { + s = isinlining ? permalloc(30) : tmpalloc(30); + sprintf(s, " .long 0%llo", word); + send_passt(IP_ASM, s); + word = inwd = 0; + } +} +#endif + +/* make a name look like an external name in the local machine */ +char * +exname(char *p) +{ + if (p == NULL) + return ""; + return p; +} + +/* + * map types which are not defined on the local machine + */ +TWORD +ctype(TWORD type) +{ + switch (BTYPE(type)) { + case LONG: + MODTYPE(type,INT); + break; + case ULONG: + MODTYPE(type,UNSIGNED); + break; + case LDOUBLE: + MODTYPE(type,DOUBLE); + break; + } + return (type); +} + +/* + * Print out a string of characters. + * Assume that the assembler understands C-style escape + * sequences. + */ +void +instring(struct symtab *sp) +{ + char *s, *str; + + defloc(sp); + str = sp->sname; + + /* be kind to assemblers and avoid long strings */ + printf("\t.ascii \""); + for (s = str; *s != 0; ) { + if (*s++ == '\\') { + (void)esccon(&s); + } + if (s - str > 60) { + fwrite(str, 1, s - str, stdout); + printf("\"\n\t.ascii \""); + str = s; + } + } + fwrite(str, 1, s - str, stdout); + printf("\\0\"\n"); +} + +/* curid is a variable which is defined but + * is not initialized (and not a function ); + * This routine returns the stroage class for an uninitialized declaration + */ +int +noinit() +{ + return(EXTERN); +} + +void +calldec(NODE *p, NODE *q) +{ +} + +void +extdec(struct symtab *q) +{ +} + +/* make a common declaration for id, if reasonable */ +void +defzero(struct symtab *sp) +{ + int off; + + off = tsize(sp->stype, sp->sdf, sp->ssue); + off = (off+(SZINT-1))/SZINT; + printf(" .%scomm ", sp->sclass == STATIC ? "l" : ""); + if (sp->slevel == 0) + printf("%s,0%o\n", exname(sp->soname), off); + else + printf(LABFMT ",0%o\n", sp->soffset, off); +} + +/* + * set fsz bits in sequence to zero. + */ +void +zbits(OFFSZ off, int fsz) +{ + cerror("zbits"); +} + +/* + * Initialize a bitfield. + */ +void +infld(CONSZ off, int fsz, CONSZ val) +{ +// if (idebug) +// printf("infld off %lld, fsz %d, val %lld inbits %d\n", +// off, fsz, val, inbits); + cerror("infld"); +} + +/* + * print out a constant node, may be associated with a label. + * Do not free the node after use. + * off is bit offset from the beginning of the aggregate + * fsz is the number of bits this is referring to + */ +void +ninval(CONSZ off, int fsz, NODE *p) +{ + cerror("ninval"); +} + + +/* + * Give target the opportunity of handling pragmas. + */ +int +mypragma(char *str) +{ + return 0; +} + +/* + * Called when a identifier has been declared, to give target last word. + */ +void +fixdef(struct symtab *sp) +{ +} + +void +pass1_lastchance(struct interpass *ip) +{ +} + diff --git a/compilers/pcc/pcc-1.0.0/arch/pdp10/local2.c b/compilers/pcc/pcc-1.0.0/arch/pdp10/local2.c new file mode 100644 index 00000000..3383c5dd --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/pdp10/local2.c @@ -0,0 +1,1321 @@ +/* $Id: local2.c,v 1.102 2008/11/22 16:12:25 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass2.h" +# include + +# define putstr(s) fputs((s), stdout) + +void acon(FILE *, NODE *p); +int argsize(NODE *p); +void genargs(NODE *p); + +static int offlab; +int offarg; +static int addto; +static int regoff[16]; + +void +deflab(int label) +{ + printf(LABFMT ":\n", label); +} + +void +prologue(struct interpass_prolog *ipp) +{ + int i, j; + + if (ipp->ipp_vis) + printf(" .globl %s\n", ipp->ipp_name); + printf("%s:\n", ipp->ipp_name); + addto = p2maxautooff; + if (addto >= AUTOINIT/SZCHAR) + addto -= AUTOINIT/SZCHAR; + addto /= SZINT/SZCHAR; /* use words here */ + printf(" push %s,%s\n",rnames[STKREG], rnames[FPREG]); + printf(" move %s,%s\n", rnames[FPREG],rnames[STKREG]); + + for (i = ipp->ipp_regs[0], j = 0; i ; i >>= 1, j++) { + if (i & 1) + regoff[j] = addto++; + } + if (addto) + printf(" addi %s,0%o\n", rnames[STKREG], addto); + + for (i = ipp->ipp_regs[0], j = 0; i ; i >>= 1, j++) { + if (i & 1) + printf(" movem %s,%d(%s)\n", + rnames[j], regoff[j], rnames[STKREG]); + } +} + +void +eoftn(struct interpass_prolog *ipp) +{ + int i, j; + + if (ipp->ipp_ip.ip_lbl == 0) + return; /* no code needs to be generated */ + for (i = ipp->ipp_regs[0], j = 0; i ; i >>= 1, j++) { + if (i & 1) + printf(" move %s,%d(%s)\n", + rnames[j], regoff[j], rnames[STKREG]); + } + printf(" move %s,%s\n", rnames[STKREG], rnames[FPREG]); + printf(" pop %s,%s\n", rnames[STKREG], rnames[FPREG]); + printf(" popj %s,\n", rnames[STKREG]); +} + +#if 0 +void +prologue(int regs, int autos) +{ + int i, addto; + + offlab = getlab2(); + if (regs < 0 || autos < 0) { + /* + * non-optimized code, jump to epilogue for code generation. + */ + ftlab1 = getlab2(); + ftlab2 = getlab2(); + printf(" jrst L%d\n", ftlab1); + printf("L%d:\n", ftlab2); + } else { + /* + * We here know what register to save and how much to + * add to the stack. + */ + autos = autos + (SZINT-1); + addto = (autos - AUTOINIT)/SZINT + (MAXRVAR-regs); + if (addto || gflag) { + printf(" push %s,%s\n",rnames[017], rnames[016]); + printf(" move %s,%s\n", rnames[016],rnames[017]); + for (i = regs; i < MAXRVAR; i++) { + int db = ((i+1) < MAXRVAR); + printf(" %smovem %s,0%o(%s)\n", + db ? "d" : "", + rnames[i+1], i+1-regs, rnames[016]); + if (db) + i++; + } + if (addto) + printf(" addi %s,0%o\n", rnames[017], addto); + } else + offarg = 1; + } +} + +/* + * End of block. + */ +void +eoftn(int regs, int autos, int retlab) +{ + register OFFSZ spoff; /* offset from stack pointer */ + int i; + + spoff = autos + (SZINT-1); + if (spoff >= AUTOINIT) + spoff -= AUTOINIT; + spoff /= SZINT; + /* return from function code */ + printf("L%d:\n", retlab); + if (gflag || isoptim == 0 || autos != AUTOINIT || regs != MAXRVAR) { + for (i = regs; i < MAXRVAR; i++) { + int db = ((i+1) < MAXRVAR); + printf(" %smove %s,0%o(%s)\n", db ? "d" : "", + rnames[i+1], i+1-regs, rnames[016]); + if (db) + i++; + } + printf(" move %s,%s\n", rnames[017], rnames[016]); + printf(" pop %s,%s\n", rnames[017], rnames[016]); + } + printf(" popj %s,\n", rnames[017]); + + /* Prolog code */ + if (isoptim == 0) { + printf("L%d:\n", ftlab1); + printf(" push %s,%s\n", rnames[017], rnames[016]); + printf(" move %s,%s\n", rnames[016], rnames[017]); + for (i = regs; i < MAXRVAR; i++) { + int db = ((i+1) < MAXRVAR); + printf(" %smovem %s,0%o(%s)\n", db ? "d" : "", + rnames[i+1], i+1-regs, rnames[016]); + spoff++; + if (db) + i++, spoff++; + } + if (spoff) + printf(" addi %s,0%llo\n", rnames[017], spoff); + printf(" jrst L%d\n", ftlab2); + } + printf(" .set " LABFMT ",0%o\n", offlab, MAXRVAR-regs); + offarg = isoptim = 0; +} +#endif + +/* + * add/sub/... + * + * Param given: + * R - Register + * M - Memory + * C - Constant + */ +void +hopcode(int f, int o) +{ + cerror("hopcode: f %d %d", f, o); +} + +char * +rnames[] = { /* keyed to register number tokens */ + "%0", "%1", "%2", "%3", "%4", "%5", "%6", "%7", + "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17", + "%0", "%1", "%2", "%3", "%4", "%5", "%6", "%7", + "%10", "%11", "%12", "%13", "%14", "%15", +}; + +int +tlen(p) NODE *p; +{ + switch(p->n_type) { + case CHAR: + case UCHAR: + return(1); + + case SHORT: + case USHORT: + return(SZSHORT/SZCHAR); + + case DOUBLE: + return(SZDOUBLE/SZCHAR); + + case INT: + case UNSIGNED: + case LONG: + case ULONG: + return(SZINT/SZCHAR); + + case LONGLONG: + case ULONGLONG: + return SZLONGLONG/SZCHAR; + + default: + if (!ISPTR(p->n_type)) + cerror("tlen type %d not pointer"); + return SZPOINT(0)/SZCHAR; + } +} + +static char * +binskip[] = { + "e", /* jumpe */ + "n", /* jumpn */ + "le", /* jumple */ + "l", /* jumpl */ + "ge", /* jumpge */ + "g", /* jumpg */ +}; + +/* + * Extract the higher 36 bits from a longlong. + */ +static CONSZ +gethval(CONSZ lval) +{ + CONSZ hval = (lval >> 35) & 03777777777LL; + + if ((hval & 03000000000LL) == 03000000000LL) { + hval |= 0777000000000LL; + } else if ((hval & 03000000000LL) == 02000000000LL) { + hval &= 01777777777LL; + hval |= 0400000000000LL; + } + return hval; +} + +/* + * Do a binary comparision, and jump accordingly. + */ +static void +twocomp(NODE *p) +{ + int o = p->n_op; + extern int negrel[]; + int isscon = 0, iscon = p->n_right->n_op == ICON; + + if (o < EQ || o > GT) + cerror("bad binary conditional branch: %s", opst[o]); + + if (iscon && p->n_right->n_name[0] != 0) { + printf(" cam%s ", binskip[negrel[o-EQ]-EQ]); + adrput(stdout, getlr(p, 'L')); + putchar(','); + printf("[ .long "); + adrput(stdout, getlr(p, 'R')); + putchar(']'); + printf("\n jrst L%d\n", p->n_label); + return; + } + if (iscon) + isscon = p->n_right->n_lval >= 0 && + p->n_right->n_lval < 01000000; + + printf(" ca%c%s ", iscon && isscon ? 'i' : 'm', + binskip[negrel[o-EQ]-EQ]); + adrput(stdout, getlr(p, 'L')); + putchar(','); + if (iscon && (isscon == 0)) { + printf("[ .long "); + adrput(stdout, getlr(p, 'R')); + putchar(']'); + } else + adrput(stdout, getlr(p, 'R')); + printf("\n jrst L%d\n", p->n_label); +} + +/* + * Compare byte/word pointers. + * XXX - do not work for highest bit set in address + */ +static void +ptrcomp(NODE *p) +{ + printf(" rot "); adrput(stdout, getlr(p, 'L')); printf(",6\n"); + printf(" rot "); adrput(stdout, getlr(p, 'R')); printf(",6\n"); + twocomp(p); +} + +/* + * Do a binary comparision of two long long, and jump accordingly. + * XXX - can optimize for constants. + */ +static void +twollcomp(NODE *p) +{ + int o = p->n_op; + int iscon = p->n_right->n_op == ICON; + int m = 0; /* XXX gcc */ + + if (o < EQ || o > GT) + cerror("bad long long conditional branch: %s", opst[o]); + + /* Special strategy for equal/not equal */ + if (o == EQ || o == NE) { + if (o == EQ) + m = getlab2(); + printf(" came "); + upput(getlr(p, 'L'), SZLONG); + putchar(','); + if (iscon) + printf("[ .long "); + upput(getlr(p, 'R'), SZLONG); + if (iscon) + putchar(']'); + printf("\n jrst L%d\n", o == EQ ? m : p->n_label); + printf(" cam%c ", o == EQ ? 'n' : 'e'); + adrput(stdout, getlr(p, 'L')); + putchar(','); + if (iscon) + printf("[ .long "); + adrput(stdout, getlr(p, 'R')); + if (iscon) + putchar(']'); + printf("\n jrst L%d\n", p->n_label); + if (o == EQ) + printf("L%d:\n", m); + return; + } + /* First test highword */ + printf(" cam%ce ", o == GT || o == GE ? 'l' : 'g'); + adrput(stdout, getlr(p, 'L')); + putchar(','); + if (iscon) + printf("[ .long "); + adrput(stdout, getlr(p, 'R')); + if (iscon) + putchar(']'); + printf("\n jrst L%d\n", p->n_label); + + /* Test equality */ + printf(" came "); + adrput(stdout, getlr(p, 'L')); + putchar(','); + if (iscon) + printf("[ .long "); + adrput(stdout, getlr(p, 'R')); + if (iscon) + putchar(']'); + printf("\n jrst L%d\n", m = getlab2()); + + /* Test lowword. Only works with pdp10 format for longlongs */ + printf(" cam%c%c ", o == GT || o == GE ? 'l' : 'g', + o == LT || o == GT ? 'e' : ' '); + upput(getlr(p, 'L'), SZLONG); + putchar(','); + if (iscon) + printf("[ .long "); + upput(getlr(p, 'R'), SZLONG); + if (iscon) + putchar(']'); + printf("\n jrst L%d\n", p->n_label); + printf("L%d:\n", m); +} + +/* + * Print the correct instruction for constants. + */ +static void +constput(NODE *p) +{ + CONSZ val = p->n_right->n_lval; + int reg = p->n_left->n_rval; + + /* Only numeric constant */ + if (p->n_right->n_name[0] == '\0') { + if (val == 0) { + printf("movei %s,0", rnames[reg]); + } else if ((val & 0777777000000LL) == 0) { + printf("movei %s,0%llo", rnames[reg], val); + } else if ((val & 0777777) == 0) { + printf("hrlzi %s,0%llo", rnames[reg], val >> 18); + } else { + printf("move %s,[ .long 0%llo]", rnames[reg], + szty(p->n_right->n_type) > 1 ? val : + val & 0777777777777LL); + } + /* Can have more tests here, hrloi etc */ + return; + } else { + printf("xmovei %s,%s", rnames[reg], p->n_right->n_name); + if (val) + printf("+" CONFMT, val); + } +} + +/* + * Return true if the constant can be bundled in an instruction (immediate). + */ +static int +oneinstr(NODE *p) +{ + if (p->n_name[0] != '\0') + return 0; + if ((p->n_lval & 0777777000000ULL) != 0) + return 0; + return 1; +} + +/* + * Emit a halfword or byte instruction, from OREG to REG. + * Sign extension must also be done here. + */ +static void +emitshort(NODE *p) +{ + CONSZ off = p->n_lval; + TWORD type = p->n_type; + int reg = p->n_rval; + int issigned = !ISUNSIGNED(type); + int ischar = type == CHAR || type == UCHAR; + int reg1 = getlr(p, '1')->n_rval; + + if (off < 0) { /* argument, use move instead */ + printf(" move "); + } else if (off == 0 && p->n_name[0] == 0) { + printf(" ldb %s,%s\n", rnames[reg1], rnames[reg]); + /* XXX must sign extend here even if not necessary */ + switch (type) { + case CHAR: + printf(" lsh %s,033\n", rnames[reg1]); + printf(" ash %s,-033\n", rnames[reg1]); + break; + case SHORT: + printf(" hrre %s,%s\n", + rnames[reg1], rnames[reg1]); + break; + } + return; + } else if (ischar) { + if (off >= 0700000000000LL && p->n_name[0] != '\0') { + cerror("emitsh"); + /* reg contains index integer */ +// if (!istreg(reg)) +// cerror("emitshort !istreg"); + printf(" adjbp %s,[ .long 0%llo+%s ]\n", + rnames[reg], off, p->n_name); + printf(" ldb "); + adrput(stdout, getlr(p, '1')); + printf(",%s\n", rnames[reg]); + goto signe; + } + printf(" ldb "); + adrput(stdout, getlr(p, '1')); + if (off) + printf(",[ .long 0%02o11%02o%06o ]\n", + (int)(27-(9*(off&3))), reg, (int)off/4); + else + printf(",%s\n", rnames[reg]); +signe: if (issigned) { + printf(" lsh "); + adrput(stdout, getlr(p, '1')); + printf(",033\n ash "); + adrput(stdout, getlr(p, '1')); + printf(",-033\n"); + } + return; + } else { + printf(" h%cr%c ", off & 1 ? 'r' : 'l', + issigned ? 'e' : 'z'); + } + p->n_lval /= (ischar ? 4 : 2); + adrput(stdout, getlr(p, '1')); + putchar(','); + adrput(stdout, getlr(p, 'L')); + putchar('\n'); +} + +/* + * Store a short from a register. Destination is a OREG. + */ +static void +storeshort(NODE *p) +{ + NODE *l = p->n_left; + CONSZ off = l->n_lval; + int reg = l->n_rval; + int ischar = BTYPE(p->n_type) == CHAR || BTYPE(p->n_type) == UCHAR; + + if (l->n_op == NAME) { + if (ischar) { + printf(" dpb "); + adrput(stdout, getlr(p, 'R')); + printf(",[ .long 0%02o%010o+%s ]\n", + 070+((int)off&3), (int)(off/4), l->n_name); + return; + } + printf(" hr%cm ", off & 1 ? 'r' : 'l'); + l->n_lval /= 2; + adrput(stdout, getlr(p, 'R')); + putchar(','); + adrput(stdout, getlr(p, 'L')); + putchar('\n'); + return; + } + + if (off || reg == FPREG) { /* Can emit halfword instructions */ + if (off < 0) { /* argument, use move instead */ + printf(" movem "); + } else if (ischar) { + printf(" dpb "); + adrput(stdout, getlr(p, '1')); + printf(",[ .long 0%02o11%02o%06o ]\n", + (int)(27-(9*(off&3))), reg, (int)off/4); + return; + } else { + printf(" hr%cm ", off & 1 ? 'r' : 'l'); + } + l->n_lval /= 2; + adrput(stdout, getlr(p, 'R')); + putchar(','); + adrput(stdout, getlr(p, 'L')); + } else { + printf(" dpb "); + adrput(stdout, getlr(p, 'R')); + putchar(','); + l = getlr(p, 'L'); + l->n_op = REG; + adrput(stdout, l); + l->n_op = OREG; + } + putchar('\n'); +} + +/* + * Multiply a register with a constant. + */ +static void +imuli(NODE *p) +{ + NODE *r = p->n_right; + + if (r->n_lval >= 0 && r->n_lval <= 0777777) { + printf(" imuli "); + adrput(stdout, getlr(p, 'L')); + printf(",0%llo\n", r->n_lval); + } else { + printf(" imul "); + adrput(stdout, getlr(p, 'L')); + printf(",[ .long 0%llo ]\n", r->n_lval & 0777777777777LL); + } +} + +/* + * Divide a register with a constant. + */ +static void +idivi(NODE *p) +{ + NODE *r = p->n_right; + + if (r->n_lval >= 0 && r->n_lval <= 0777777) { + printf(" idivi "); + adrput(stdout, getlr(p, '1')); + printf(",0%llo\n", r->n_lval); + } else { + printf(" idiv "); + adrput(stdout, getlr(p, '1')); + printf(",[ .long 0%llo ]\n", r->n_lval & 0777777777777LL); + } +} + +/* + * move a constant into a register. + */ +static void +xmovei(NODE *p) +{ + /* + * Trick: If this is an unnamed constant, just move it directly, + * otherwise use xmovei to get section number. + */ + if (p->n_name[0] == '\0' || p->n_lval > 0777777) { + printf(" "); + zzzcode(p, 'D'); + putchar(' '); + adrput(stdout, getlr(p, '1')); + putchar(','); + zzzcode(p, 'E'); + } else { + printf(" xmovei "); + adrput(stdout, getlr(p, '1')); + printf(",%s", p->n_name); + if (p->n_lval != 0) + printf("+0%llo", p->n_lval); + } + putchar('\n'); +} + +static void +printcon(NODE *p) +{ + CONSZ cz; + + p = p->n_left; + if (p->n_lval >= 0700000000000LL) { + /* converted to pointer in clocal() */ + conput(0, p); + return; + } + if (p->n_lval == 0 && p->n_name[0] == '\0') { + putchar('0'); + return; + } + if (BTYPE(p->n_type) == CHAR || BTYPE(p->n_type) == UCHAR) + cz = (p->n_lval/4) | ((p->n_lval & 3) << 30); + else + cz = (p->n_lval/2) | (((p->n_lval & 1) + 5) << 30); + cz |= 0700000000000LL; + printf("0%llo", cz); + if (p->n_name[0] != '\0') + printf("+%s", p->n_name); +} + +static void +putcond(NODE *p) +{ + char *c = 0; /* XXX gcc */ + + switch (p->n_op) { + case EQ: c = "e"; break; + case NE: c = "n"; break; + case LE: c = "le"; break; + case LT: c = "l"; break; + case GT: c = "g"; break; + case GE: c = "ge"; break; + default: + cerror("putcond"); + } + printf("%s", c); +} + +void +zzzcode(NODE *p, int c) +{ + NODE *l; + CONSZ hval; + + switch (c) { + case 'A': /* ildb right arg */ + adrput(stdout, p->n_left->n_left); + break; + + case 'B': /* remove from stack after subroutine call */ + if (p->n_qual) + printf(" subi %%17,0%o\n", p->n_qual); + break; + + case 'C': + constput(p); + break; + + case 'D': /* Find out which type of const load insn to use */ + if (p->n_op != ICON) + cerror("zzzcode not ICON"); + if (p->n_name[0] == '\0') { + if ((p->n_lval <= 0777777) && (p->n_lval > 0)) + printf("movei"); + else if ((p->n_lval & 0777777) == 0) + printf("hrlzi"); + else + printf("move"); + } else + printf("move"); + break; + + case 'E': /* Print correct constant expression */ + if (p->n_name[0] == '\0') { + if ((p->n_lval <= 0777777) && (p->n_lval > 0)){ + printf("0%llo", p->n_lval); + } else if ((p->n_lval & 0777777) == 0) { + printf("0%llo", p->n_lval >> 18); + } else { + if (p->n_lval < 0) + printf("[ .long -0%llo]", -p->n_lval); + else + printf("[ .long 0%llo]", p->n_lval); + } + } else { + if (p->n_lval == 0) + printf("[ .long %s]", p->n_name); + else + printf("[ .long %s+0%llo]", + p->n_name, p->n_lval); + } + break; + + case 'G': /* structure argument */ + printf(" addl %%17,0%o\n", p->n_stsize/(SZINT/SZCHAR)); + printf(" foo...\n"); + break; + + case 'P': + p = getlr(p, 'R'); + /* FALLTHROUGH */ + case 'O': + /* + * Print long long expression. + */ + hval = gethval(p->n_lval); + printf("[ .long 0%llo,0%llo", hval, + (p->n_lval & 0377777777777LL) | (hval & 0400000000000LL)); + if (p->n_name[0] != '\0') + printf("+%s", p->n_name); + printf(" ]"); + break; + + case 'F': /* Print an "opsimp" instruction based on its const type */ + hopcode(oneinstr(p->n_right) ? 'C' : 'R', p->n_op); + break; + + case 'H': /* Print a small constant */ + p = p->n_right; + printf("0%llo", p->n_lval & 0777777); + break; + + case 'Q': /* two-param long long comparisions */ + twollcomp(p); + break; + + case 'R': /* two-param conditionals */ + twocomp(p); + break; + + case 'U': + emitshort(p); + break; + + case 'V': + storeshort(p); + break; + + case 'Z': + ptrcomp(p); + break; + + case 'a': + imuli(p); + break; + + case 'b': + idivi(p); + break; + + case 'c': + xmovei(p); + break; + + case 'd': + printcon(p); + break; + + case 'e': + putcond(p); + break; + + case 'g': + if (p->n_right->n_op != OREG || p->n_right->n_lval != 0) + comperr("bad Zg oreg"); + printf("%s", rnames[p->n_right->n_rval]); + break; + +#if 0 + case '1': /* double upput */ + p = getlr(p, '1'); + p->n_rval += 2; + adrput(stdout, p); + p->n_rval -= 2; + break; +#endif + + case 'i': /* Write instruction for short load from name */ + l = getlr(p, 'L'); + printf(" h%cr%c %s,%s+" CONFMT "\n", + l->n_lval & 1 ? 'r' : 'l', + ISUNSIGNED(p->n_type) ? 'z' : 'e', + rnames[getlr(p, '1')->n_rval], + l->n_name, l->n_lval >> 1); + break; + + default: + cerror("zzzcode %c", c); + } +} + +/* set up temporary registers */ +void +setregs() +{ + fregs = 7; /* 7 free regs on PDP10 (1-7) */ +} + +/*ARGSUSED*/ +int +rewfld(NODE *p) +{ + return(1); +} + +int +fldexpand(NODE *p, int cookie, char **cp) +{ + return 0; +} + +int +flshape(NODE *p) +{ + register int o = p->n_op; + + return (o == REG || o == NAME || o == ICON || + (o == OREG && (!R2TEST(p->n_rval) || tlen(p) == 1))); +} + +/* INTEMP shapes must not contain any temporary registers */ +int +shtemp(NODE *p) +{ + return(0); +} + +int +shumul(NODE *p, int order) +{ + register int o; + + if (x2debug) { + int val; + printf("shumul(%p)\n", p); + eprint(p, 0, &val, &val); + } + + o = p->n_op; +#if 0 + if (o == NAME || (o == OREG && !R2TEST(p->n_rval)) || o == ICON) + return(STARNM); +#endif + +#if 0 + if ((o == INCR) && + (p->n_left->n_op == REG && p->n_right->n_op == ICON) && + p->n_right->n_name[0] == '\0') { + switch (p->n_type) { + case CHAR|PTR: + case UCHAR|PTR: + o = 1; + break; + + case SHORT|PTR: + case USHORT|PTR: + o = 2; + break; + + case INT|PTR: + case UNSIGNED|PTR: + case LONG|PTR: + case ULONG|PTR: + case FLOAT|PTR: + o = 4; + break; + + case DOUBLE|PTR: + case LONGLONG|PTR: + case ULONGLONG|PTR: + o = 8; + break; + + default: + if (ISPTR(p->n_type) && + ISPTR(DECREF(p->n_type))) { + o = 4; + break; + } else + return(0); + } + return( 0); + } +#endif + return( SRNOPE ); +} + +void +adrcon(CONSZ val) +{ + cerror("adrcon: val %llo\n", val); +} + +void +conput(FILE *fp, NODE *p) +{ + switch (p->n_op) { + case ICON: + if (p->n_lval != 0) { + acon(stdout, p); + if (p->n_name[0] != '\0') + putchar('+'); + } + if (p->n_name[0] != '\0') + printf("%s", p->n_name); + if (p->n_name[0] == '\0' && p->n_lval == 0) + putchar('0'); + return; + + case REG: + putstr(rnames[p->n_rval]); + return; + + default: + cerror("illegal conput"); + } +} + +/*ARGSUSED*/ +void +insput(NODE *p) +{ + cerror("insput"); +} + +/* + * Write out the upper address, like the upper register of a 2-register + * reference, or the next memory location. + */ +void +upput(NODE *p, int size) +{ + + size /= SZLONG; + switch (p->n_op) { + case REG: + putstr(rnames[p->n_rval + size]); + break; + + case NAME: + case OREG: + p->n_lval += size; + adrput(stdout, p); + p->n_lval -= size; + break; + case ICON: + printf(CONFMT, p->n_lval >> (36 * size)); + break; + default: + cerror("upput bad op %d size %d", p->n_op, size); + } +} + +void +adrput(FILE *fp, NODE *p) +{ + int r; + /* output an address, with offsets, from p */ + + if (p->n_op == FLD) + p = p->n_left; + + switch (p->n_op) { + + case NAME: + if (p->n_name[0] != '\0') + fputs(p->n_name, fp); + if (p->n_lval != 0) + fprintf(fp, "+" CONFMT, p->n_lval & 0777777777777LL); + return; + + case OREG: + r = p->n_rval; +#if 0 + if (R2TEST(r)) { /* double indexing */ + register int flags; + + flags = R2UPK3(r); + if (flags & 1) + putc('*', fp); + if (flags & 4) + putc('-', fp); + if (p->n_lval != 0 || p->n_name[0] != '\0') + acon(p); + if (R2UPK1(r) != 100) + printf("(%s)", rnames[R2UPK1(r)]); + if (flags & 2) + putchar('+'); + printf("[%s]", rnames[R2UPK2(r)]); + return; + } +#endif + if (R2TEST(r)) + cerror("adrput: unwanted double indexing: r %o", r); + if (p->n_rval != FPREG && p->n_lval < 0 && p->n_name[0]) { + fprintf(fp, "%s", p->n_name); + acon(fp, p); + fprintf(fp, "(%s)", rnames[p->n_rval]); + return; + } + if (p->n_lval < 0 && p->n_rval == FPREG && offarg) { + p->n_lval -= offarg-2; acon(fp, p); p->n_lval += offarg-2; + } else if (p->n_lval != 0) + acon(fp, p); + if (p->n_name[0] != '\0') + fprintf(fp, "%s%s", p->n_lval ? "+" : "", p->n_name); + if (p->n_lval > 0 && p->n_rval == FPREG && offlab) + fprintf(fp, "+" LABFMT, offlab); + if (p->n_lval < 0 && p->n_rval == FPREG && offarg) + fprintf(fp, "(017)"); + else + fprintf(fp, "(%s)", rnames[p->n_rval]); + return; + case ICON: + /* addressable value of the constant */ + if (p->n_lval > 0) { + acon(fp, p); + if (p->n_name[0] != '\0') + putc('+', fp); + } + if (p->n_name[0] != '\0') + fprintf(fp, "%s", p->n_name); + if (p->n_lval < 0) + acon(fp, p); + if (p->n_name[0] == '\0' && p->n_lval == 0) + putc('0', fp); + return; + + case REG: + fputs(rnames[p->n_rval], fp); + return; + + default: + cerror("illegal address, op %d", p->n_op); + return; + + } +} + +/* + * print out a constant +*/ +void +acon(FILE *fp, NODE *p) +{ + if (p->n_lval < 0 && p->n_lval > -0777777777777ULL) + fprintf(fp, "-" CONFMT, -p->n_lval); + else + fprintf(fp, CONFMT, p->n_lval); +} + +/* printf conditional and unconditional branches */ +void +cbgen(int o,int lab) +{ +} + +/* + * Do some local optimizations that must be done after optim is called. + */ +static void +optim2(NODE *p, void *arg) +{ + int op = p->n_op; + int m, ml; + NODE *l; + + /* Remove redundant PCONV's */ + if (op == PCONV) { + l = p->n_left; + m = BTYPE(p->n_type); + ml = BTYPE(l->n_type); + if ((m == INT || m == LONG || m == LONGLONG || m == FLOAT || + m == DOUBLE || m == STRTY || m == UNIONTY || + m == UNSIGNED || m == ULONG || m == ULONGLONG) && + (ml == INT || ml == LONG || ml == LONGLONG || ml == FLOAT || + ml == DOUBLE || ml == STRTY || ml == UNIONTY || + ml == UNSIGNED || ml == ULONG || + ml == ULONGLONG) && ISPTR(l->n_type)) { + *p = *l; + nfree(l); + op = p->n_op; + } else + if (ISPTR(DECREF(p->n_type)) && + (l->n_type == INCREF(STRTY))) { + *p = *l; + nfree(l); + op = p->n_op; + } else + if (ISPTR(DECREF(l->n_type)) && + (p->n_type == INCREF(INT) || + p->n_type == INCREF(STRTY) || + p->n_type == INCREF(UNSIGNED))) { + *p = *l; + nfree(l); + op = p->n_op; + } + + } + /* Add constands, similar to the one in optim() */ + if (op == PLUS && p->n_right->n_op == ICON) { + l = p->n_left; + if (l->n_op == PLUS && l->n_right->n_op == ICON && + (p->n_right->n_name[0] == '\0' || + l->n_right->n_name[0] == '\0')) { + l->n_right->n_lval += p->n_right->n_lval; + if (l->n_right->n_name[0] == '\0') + l->n_right->n_name = p->n_right->n_name; + nfree(p->n_right); + *p = *l; + nfree(l); + } + } + + /* Convert "PTR undef" (void *) to "PTR uchar" */ + /* XXX - should be done in MI code */ + if (BTYPE(p->n_type) == VOID) + p->n_type = (p->n_type & ~BTMASK) | UCHAR; + if (op == ICON) { + if ((p->n_type == (PTR|CHAR) || p->n_type == (PTR|UCHAR)) + && p->n_lval == 0 && p->n_name[0] != '\0') + p->n_lval = 0700000000000LL; + if ((p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) + && p->n_lval == 0 && p->n_name[0] != '\0') + p->n_lval = 0750000000000LL; + } + if (op == MINUS) { + if ((p->n_left->n_type == (PTR|CHAR) || + p->n_left->n_type == (PTR|UCHAR)) && + (p->n_right->n_type == (PTR|CHAR) || + p->n_right->n_type == (PTR|UCHAR))) { + l = talloc(); + l->n_op = SCONV; + l->n_type = INT; + l->n_left = p->n_right; + p->n_right = l; + l = talloc(); + l->n_op = SCONV; + l->n_type = INT; + l->n_left = p->n_left; + p->n_left = l; + } + } +} + +void +myreader(struct interpass *ipole) +{ + struct interpass *ip; + + DLIST_FOREACH(ip, ipole, qelem) { + if (ip->type != IP_NODE) + continue; + walkf(ip->ip_node, optim2, 0); + } + + if (x2debug) { + printf("myreader final tree:\n"); + printip(ipole); + } +} + +/* + * Remove some PCONVs after OREGs are created. + */ +static void +pconv2(NODE *p, void *arg) +{ + NODE *q; + + if (p->n_op == PLUS) { + if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) { + if (p->n_right->n_op != ICON) + return; + if (p->n_left->n_op != PCONV) + return; + if (p->n_left->n_left->n_op != OREG) + return; + q = p->n_left->n_left; + nfree(p->n_left); + p->n_left = q; + /* + * This will be converted to another OREG later. + */ + } + } +} + +void +mycanon(NODE *p) +{ + walkf(p, pconv2, 0); +} + +/* + * Remove last goto. + */ +void +myoptim(struct interpass *ip) +{ +} + +/* + * Return a class suitable for a specific type. + */ +int +gclass(TWORD t) +{ + return (szty(t) == 2 ? CLASSB : CLASSA); +} + +static int +argsiz(NODE *p) +{ + TWORD t = p->n_type; + + if (t == STRTY || t == UNIONTY) + return p->n_stsize/(SZINT/SZCHAR); + return szty(t); +} + +/* + * Calculate argument sizes. + */ +void +lastcall(NODE *p) +{ + NODE *op = p; + int size = 0; + + p->n_qual = 0; + if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL) + return; + for (p = p->n_right; p->n_op == CM; p = p->n_left) + if (p->n_right->n_op != ASSIGN) + size += argsiz(p->n_right); + if (p->n_op != ASSIGN) + size += argsiz(p); + op->n_qual = size; /* XXX */ +} + +void +rmove(int s, int d, TWORD t) +{ + printf(" %smove %s,%s\n", + (s > 017 ? "d" : ""), rnames[d], rnames[s]); +} + +/* + * For class c, find worst-case displacement of the number of + * registers in the array r[] indexed by class. + */ +int +COLORMAP(int c, int *r) +{ + int num; + + switch (c) { + case CLASSA: + /* there are 13 classa, so min 6 classb are needed to block */ + num = r[CLASSB] * 2; + num += r[CLASSA]; + return num < 13; + case CLASSB: + /* 7 classa may block all classb */ + num = r[CLASSB] + r[CLASSA]; + return num < 7; + } + comperr("COLORMAP"); + return 0; /* XXX gcc */ +} + +/* + * Target-dependent command-line options. + */ +void +mflags(char *str) +{ +} +/* + * Do something target-dependent for xasm arguments. + * Supposed to find target-specific constraints and rewrite them. + */ +int +myxasm(struct interpass *ip, NODE *p) +{ + return 0; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/pdp10/macdefs.h b/compilers/pcc/pcc-1.0.0/arch/pdp10/macdefs.h new file mode 100644 index 00000000..3b246feb --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/pdp10/macdefs.h @@ -0,0 +1,247 @@ +/* $Id: macdefs.h,v 1.30 2009/01/24 21:43:49 gmcgarry Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Machine-dependent defines for both passes. + */ + +/* + * Convert (multi-)character constant to integer. + * Assume: If only one value; store at left side (char size), otherwise + * treat it as an integer. + */ +#define makecc(val,i) { \ + if (i == 0) { lastcon = val; \ + } else if (i == 1) { lastcon = (lastcon << 9) | val; lastcon <<= 18; \ + } else { lastcon |= (val << (27 - (i * 9))); } } + +#define ARGINIT 36 /* # bits below fp where arguments start */ +#define AUTOINIT 36 /* # bits above fp where automatics start */ + +/* + * Storage space requirements + */ +#define SZCHAR 9 +#define SZBOOL 36 +#define SZINT 36 +#define SZFLOAT 36 +#define SZDOUBLE 72 +#define SZLDOUBLE 72 +#define SZLONG 36 +#define SZSHORT 18 +#define SZPOINT(x) 36 +#define SZLONGLONG 72 + +/* + * Alignment constraints + */ +#define ALCHAR 9 +#define ALBOOL 36 +#define ALINT 36 +#define ALFLOAT 36 +#define ALDOUBLE 36 +#define ALLDOUBLE 36 +#define ALLONG 36 +#define ALLONGLONG 36 +#define ALSHORT 18 +#define ALPOINT 36 +#define ALSTRUCT 36 +#define ALSTACK 36 + +/* + * Max values. + */ +#define MIN_CHAR -256 +#define MAX_CHAR 255 +#define MAX_UCHAR 511 +#define MIN_SHORT -131072 +#define MAX_SHORT 131071 +#define MAX_USHORT 262143 +#define MIN_INT (-0377777777777LL-1) +#define MAX_INT 0377777777777LL +#define MAX_UNSIGNED 0777777777777ULL +#define MIN_LONG (-0377777777777LL-1) +#define MAX_LONG 0377777777777LL +#define MAX_ULONG 0777777777777ULL +#define MIN_LONGLONG (000777777777777777777777LL-1) /* XXX cross */ +#define MAX_LONGLONG 000777777777777777777777LL /* XXX cross */ +#define MAX_ULONGLONG 001777777777777777777777ULL /* XXX cross */ + +/* Default char is unsigned */ +#define TARGET_STDARGS +#define CHAR_UNSIGNED +#define BOOL_TYPE INT + +/* + * Use large-enough types. + */ +typedef long long CONSZ; +typedef unsigned long long U_CONSZ; +typedef long long OFFSZ; + +#define CONFMT "0%llo" /* format for printing constants */ +#define LABFMT ".L%d" /* format for printing labels */ +#define STABLBL ".LL%d" /* format for stab (debugging) labels */ + +#undef BACKAUTO /* stack grows negatively for automatics */ +#undef BACKTEMP /* stack grows negatively for temporaries */ + +#undef FIELDOPS /* no bit-field instructions */ +#undef RTOLBYTES /* bytes are numbered left to right */ + +#define ENUMSIZE(high,low) INT /* enums are always stored in full int */ + +/* Definitions mostly used in pass2 */ + +#define BYTEOFF(x) ((x)&03) +#define wdal(k) (BYTEOFF(k)==0) +#define BITOOR(x) ((x)/36) /* bit offset to oreg offset */ + +#define STOARG(p) +#define STOFARG(p) +#define STOSTARG(p) +#define genfcall(a,b) gencall(a,b) + +#define szty(t) (((t) == DOUBLE || (t) == FLOAT || \ + (t) == LONGLONG || (t) == ULONGLONG) ? 2 : 1) + +#define shltype(o, p) \ + ((o) == REG || (o) == NAME || (o) == ICON || \ + (o) == OREG || ((o) == UMUL && shumul((p)->n_left, SOREG))) + +#undef SPECIAL_INTEGERS + +/* + * Special shapes used in code generation. + */ +#define SUSHCON (SPECIAL|6) /* unsigned short constant */ +#define SNSHCON (SPECIAL|7) /* negative short constant */ +#define SILDB (SPECIAL|8) /* use ildb here */ + +/* + * Register allocator definitions. + * + * The pdp10 has 16 general-purpose registers, but the two + * highest are used as sp and fp. Register 0 has special + * constraints in its possible use as index register. + * All regs can be used as pairs, named by the lowest number. + * In here we call the registers Rn and the pairs XRn, in assembler + * just its number prefixed with %. + * + * R1/XR1 are return registers. + * + * R0 is currently not used. + */ + +#define MAXREGS 29 /* 16 + 13 regs */ +#define NUMCLASS 2 + +#define R0 00 +#define R1 01 +#define R2 02 +#define R3 03 +#define R4 04 +#define R5 05 +#define R6 06 +#define R7 07 +#define R10 010 +#define R11 011 +#define R12 012 +#define R13 013 +#define R14 014 +#define R15 015 +#define R16 016 +#define R17 017 +#define FPREG R16 /* frame pointer */ +#define STKREG R17 /* stack pointer */ + + +#define XR0 020 +#define XR1 021 +#define XR2 022 +#define XR3 023 +#define XR4 024 +#define XR5 025 +#define XR6 026 +#define XR7 027 +#define XR10 030 +#define XR11 031 +#define XR12 032 +#define XR13 033 +#define XR14 034 + + +#define RSTATUS \ + 0, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \ + SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \ + SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, \ + SAREG|PERMREG, SAREG|PERMREG, 0, 0, \ + SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \ + SBREG, SBREG, SBREG, SBREG, SBREG, + +#define ROVERLAP \ + { XR0, -1 }, \ + { XR0, XR1, -1 }, \ + { XR1, XR2, -1 }, \ + { XR2, XR3, -1 }, \ + { XR3, XR4, -1 }, \ + { XR4, XR5, -1 }, \ + { XR5, XR6, -1 }, \ + { XR6, XR7, -1 }, \ + { XR7, XR10, -1 }, \ + { XR10, XR11, -1 }, \ + { XR11, XR12, -1 }, \ + { XR12, XR13, -1 }, \ + { XR13, XR14, -1 }, \ + { XR14, -1 }, \ + { -1 }, \ + { -1 }, \ + { R0, R1, XR1, -1 }, \ + { R1, R2, XR0, XR2, -1 }, \ + { R2, R3, XR1, XR3, -1 }, \ + { R3, R4, XR2, XR4, -1 }, \ + { R4, R5, XR3, XR5, -1 }, \ + { R5, R6, XR4, XR6, -1 }, \ + { R6, R7, XR5, XR7, -1 }, \ + { R7, R10, XR6, XR10, -1 }, \ + { R10, R11, XR7, XR11, -1 }, \ + { R11, R12, XR10, XR12, -1 }, \ + { R12, R13, XR11, XR13, -1 }, \ + { R13, R14, XR12, XR14, -1 }, \ + { R14, R15, XR13, -1 }, + +/* Return a register class based on the type of the node */ +#define PCLASS(p) (szty(p->n_type) == 2 ? SBREG : SAREG) +#define RETREG(x) (szty(x) == 2 ? XR1 : R1) +#define DECRA(x,y) (((x) >> (y*6)) & 63) /* decode encoded regs */ +#define ENCRD(x) (x) /* Encode dest reg in n_reg */ +#define ENCRA1(x) ((x) << 6) /* A1 */ +#define ENCRA2(x) ((x) << 12) /* A2 */ +#define ENCRA(x,y) ((x) << (6+y*6)) /* encode regs in int */ +#define GCLASS(x) (x < 16 ? CLASSA : CLASSB) +int COLORMAP(int c, int *r); diff --git a/compilers/pcc/pcc-1.0.0/arch/pdp10/order.c b/compilers/pcc/pcc-1.0.0/arch/pdp10/order.c new file mode 100644 index 00000000..1f695df2 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/pdp10/order.c @@ -0,0 +1,202 @@ +/* $Id: order.c,v 1.63 2008/01/15 21:47:06 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass2.h" + +int canaddr(NODE *); + +/* is it legal to make an OREG or NAME entry which has an + * offset of off, (from a register of r), if the + * resulting thing had type t */ +int +notoff(TWORD t, int r, CONSZ off, char *cp) +{ + return(0); /* YES */ +} + +int radebug = 0; + +void +offstar(NODE *p, int shape) +{ + NODE *q; + + if (x2debug) + printf("offstar(%p)\n", p); + + if( p->n_op == PLUS || p->n_op == MINUS ){ + if( p->n_right->n_op == ICON ){ + q = p->n_left; + if (q->n_op != REG) + geninsn(q, INAREG); + p->n_su = -1; + } + } + geninsn(p, INAREG); +} + +/* + * findops() failed, see if we can rewrite it to match. + */ +int +setbin(NODE *p) +{ + TWORD ty; + NODE *r, *s; + + ty = p->n_type; + switch (p->n_op) { + case MINUS: + switch (ty) { + case PTR+CHAR: + case PTR+UCHAR: + case PTR+SHORT: + case PTR+USHORT: + /* + * Must negate the right side and change op to PLUS. + */ + r = p->n_right; + if (r->n_op == ICON) { + r->n_lval = -r->n_lval; + } else { + s = talloc(); + s->n_type = r->n_type; + s->n_op = UMINUS; + s->n_left = r; + p->n_right = s; + } + p->n_op = PLUS; + return 1; + } + } + return 0; +} + +/* setup for assignment operator */ +int +setasg(NODE *p, int cookie) +{ + return(0); +} + +/* setup for unary operator */ +int +setuni(NODE *p, int cookie) +{ + return 0; +} + +int +special(NODE *p, int shape) +{ + switch (shape) { + case SUSHCON: + if (p->n_op == ICON && p->n_name[0] == '\0' && + (p->n_lval > 0 && p->n_lval <= 0777777)) + return 1; + break; + + case SNSHCON: + if (p->n_op == ICON && p->n_name[0] == '\0' && + (p->n_lval < 0 && p->n_lval > -01000000)) + return 1; + break; + case SILDB: + if (p->n_op == ASSIGN && p->n_left->n_op == REG && + p->n_right->n_op == PLUS && + p->n_right->n_left->n_op == REG && + p->n_right->n_right->n_op == ICON && + p->n_right->n_right->n_lval == 1 && + p->n_right->n_left->n_rval == p->n_left->n_rval) + return 1; + break; + } + return 0; +} + +/* + * Set evaluation order of a binary node if it differs from default. + */ +int +setorder(NODE *p) +{ + return 0; /* nothing differs on x86 */ +} + +/* + * Special handling of some instruction register allocation. + */ +struct rspecial * +nspecial(struct optab *q) +{ + return 0; /* XXX gcc */ +} + +/* + * Do the actual conversion of offstar-found OREGs into real OREGs. + */ +void +myormake(NODE *p) +{ + if (x2debug) + printf("myormake(%p)\n", p); +} + +/* + * set registers in calling conventions live. + */ +int * +livecall(NODE *p) +{ + static int r[8], *s = r; + + *s = -1; + if (p->n_op == UCALL || p->n_op == UFORTCALL || p->n_op == USTCALL || + p->n_op == FORTCALL) + return s; + for (p = p->n_right; p->n_op == CM; p = p->n_left) { + if (p->n_right->n_op == ASSIGN && + p->n_right->n_left->n_op == REG) + *s++ = p->n_right->n_left->n_rval; + } + if (p->n_op == ASSIGN && + p->n_left->n_op == REG) + *s++ = p->n_left->n_rval; + *s = -1; + return r; +} + +/* + * Signal whether the instruction is acceptable for this target. + */ +int +acceptable(struct optab *op) +{ + return 1; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/pdp10/table.c b/compilers/pcc/pcc-1.0.0/arch/pdp10/table.c new file mode 100644 index 00000000..4e140c5b --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/pdp10/table.c @@ -0,0 +1,1136 @@ +/* $Id: table.c,v 1.97 2008/02/10 19:25:44 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass2.h" + +# define TLL TLONGLONG|TULONGLONG +# define ANYSIGNED TINT|TLONG|TSHORT|TCHAR +# define ANYUSIGNED TUNSIGNED|TULONG|TUSHORT|TUCHAR +# define ANYFIXED ANYSIGNED|ANYUSIGNED +# define TUWORD TUNSIGNED|TULONG +# define TSWORD TINT|TLONG +# define TWORD TUWORD|TSWORD + +struct optab table[] = { +{ -1, FORREW,SANY,TANY,SANY,TANY,REWRITE,-1,"", }, +/* + * A bunch of pointer conversions. + * First pointer to integer. + */ +/* Convert char pointer to int */ +{ SCONV, INAREG, + SAREG|SAREG, TPTRTO|TCHAR|TUCHAR, + SANY, TWORD, + NAREG, RLEFT, + " lsh AL,2\n" + " move A1,AL\n" + " lsh A1,-040\n" + " trz A1,074\n" + " ior AL,A1\n" + " tlz AL,0740000\n", }, + +/* Convert short pointer to int */ +{ SCONV, INAREG, + SAREG|SAREG, TPTRTO|TSHORT|TUSHORT, + SANY, TWORD, + NAREG, RLEFT, + " lsh AL,2\n" + " move A1,AL\n" + " lsh A1,-041\n" + " trz A1,2\n" + " ior AL,A1\n" + " tlz AL,0740000\n", }, + +/* Convert int/unsigned/long/ulong/struct/union/func ptr to int */ +{ SCONV, INAREG, + SAREG|SAREG, TPTRTO|TWORD|TSTRUCT|TPOINT, + SANY, TWORD, + 0, RLEFT, + " lsh AL,2\n", }, + +/* + * Convert int/long to pointers. + */ +/* Convert int to char pointer */ +{ PCONV, INAREG, + SAREG, TWORD, + SANY, TPTRTO|TCHAR|TUCHAR, + NAREG, RLEFT, + " move A1,AL\n" + " lsh A1,036\n" + " tlo A1,0700000\n" + " tlz A1,0040000\n" + " lsh AL,-2\n" + " ior AL,A1\n", }, + +/* Convert int/long to short pointer */ +{ PCONV, INAREG, + SAREG, TWORD, + SANY, TPTRTO|TSHORT|TUSHORT, + NAREG, RLEFT, + " move A1,AL\n" + " lsh AL,-2\n" + " tlo AL,0750000\n" + " lsh A1,035\n" + " tlz A1,0760000\n" + " add AL,A1\n", }, + +/* Convert int/long to int/struct/multiple ptr */ +{ PCONV, INAREG, + SAREG, TWORD, + SANY, TPOINT|TWORD|TSTRUCT, + 0, RLEFT, + " lsh AL,-2\n", }, + +/* + * Pointer to pointer conversions. + */ +/* Convert char ptr to short ptr */ +{ PCONV, INAREG, + SAREG, TPTRTO|TCHAR|TUCHAR, + SANY, TPTRTO|TSHORT|TUSHORT, + 0, RLEFT, + " tlo AL,050000\n" + " tlne AL,020000\n" + " tlz AL,010000\n", }, + +/* Convert char/short pointer to int/struct/multiple ptr */ +{ PCONV, INAREG, + SAREG, TPTRTO|TCHAR|TUCHAR|TSHORT|TUSHORT, + SANY, TPOINT|TWORD|TSTRUCT, + 0, RLEFT, + " tlz AL,0770000\n", }, + +/* Convert short pointer to char ptr */ +{ PCONV, INAREG, + SAREG, TPTRTO|TSHORT|TUSHORT, + SANY, TPTRTO|TCHAR|TUCHAR, + 0, RLEFT, + " tlz AL,050000\n", }, + +/* Convert int/struct/foo pointer to char ptr */ +{ PCONV, INAREG, + SAREG, TPOINT|TWORD|TSTRUCT, + SANY, TPTRTO|TCHAR|TUCHAR, + 0, RLEFT, + " tlo AL,0700000\n", }, + +/* Convert int/struct/foo pointer to short ptr */ +{ PCONV, INAREG, + SAREG, TPTRTO|TWORD|TSTRUCT, + SANY, TPTRTO|TSHORT|TUSHORT, + 0, RLEFT, + " tlo AL,0750000\n", }, + +/* + * A bunch conversions of integral<->integral types + */ + +/* convert short/char to int. This is done when register is loaded */ +{ SCONV, INAREG, + SAREG, TSHORT|TUSHORT|TCHAR|TUCHAR|TWORD, + SANY, TWORD, + 0, RLEFT, + "", }, + +/* convert int to short/char. This is done when register is loaded */ +{ SCONV, INAREG, + SAREG, TWORD, + SANY, TSHORT|TUSHORT|TCHAR|TUCHAR|TWORD, + 0, RLEFT, + "", }, + +/* convert int/long to unsigned long long */ +{ SCONV, INAREG, + SAREG|SAREG|SNAME|SOREG, TWORD, + SANY, TULONGLONG, + NAREG|NASL, RESC1, + " move U1,AL\n" + " setz A1,\n" + " tlze U1,0400000\n" + " tro A1,01\n" , }, + +/* convert int/long to long long */ +{ SCONV, INAREG, + SAREG|SAREG|SNAME|SOREG, TWORD, + SANY, TLONGLONG, + NAREG|NASL, RESC1, + " move U1,AL\n" + " move A1,U1\n" + " ash A1,-043\n", }, + +/* convert uchar/ushort to (unsigned) long long */ +{ SCONV, INAREG, + SAREG|SAREG|SNAME|SOREG, TUCHAR|TUSHORT, + SANY, TLL, + NAREG|NASL, RESC1, + " move U1,AL\n" + " setz A1,\n", }, + +/* convert long long to int/long */ +{ SCONV, INAREG, + SAREG|SAREG|SNAME|SOREG, TLL, + SANY, TWORD, + NAREG|NASL, RESC1, + " move A1,UL\n", }, + +/* convert long long to unsigned char - XXX - signed char */ +{ SCONV, INAREG, + SAREG|SAREG|SNAME|SOREG, TLL, + SANY, TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " move A1,UL\n" + " andi A1,0777\n", }, + +/* convert long long to short - XXX - signed short */ +{ SCONV, INAREG, + SAREG|SAREG|SNAME|SOREG, TLL, + SANY, TSHORT|TUSHORT, + NAREG|NASL, RESC1, + " move A1,UL\n" + " hrrz A1,A1\n", }, + +/* floating point conversions */ +{ SCONV, INAREG, + SAREG|SAREG|SNAME|SOREG, TDOUBLE|TFLOAT, + SANY, TWORD, + NAREG|NASL, RESC1, + " fix A1,AL\n", }, + +{ SCONV, INAREG, + SAREG|SAREG|SNAME|SOREG, TWORD, + SANY, TFLOAT, + NAREG|NASL, RESC1, + " fltr A1,AL\n", }, + +{ SCONV, INAREG, + SAREG|SAREG|SNAME|SOREG, TWORD, + SANY, TDOUBLE, + NAREG|NASL, RESC1, + " fltr A1,AL\n setz U1,\n", }, + +{ SCONV, INAREG, + SAREG|SAREG|SNAME|SOREG, TDOUBLE, + SANY, TFLOAT, + NAREG|NASL, RESC1, + " move A1,AL\n", }, + +{ SCONV, INAREG, + SAREG|SAREG|SNAME|SOREG, TFLOAT, + SANY, TDOUBLE, + NAREG|NASL, RESC1, + " move A1,AL\n setz U1,\n", }, + +/* + * Subroutine calls. + */ + +{ UCALL, FOREFF, + SCON, TANY, + SANY, TANY, + 0, 0, /* should be 0 */ + " pushj 017,AL\nZB", }, + +{ CALL, FOREFF, + SCON, TANY, + SANY, TANY, + 0, 0, /* should be 0 */ + " pushj 017,AL\nZB", }, + +{ UCALL, INAREG, + SCON, TANY, + SANY, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT|TFLOAT|TPOINT, + NAREG, RESC1, /* should be 0 */ + " pushj 017,AL\nZB", }, + +{ CALL, INAREG, + SCON, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + " pushj 017,AL\nZB", }, + +{ UCALL, INAREG, + SAREG|SAREG, TANY, + SANY, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT|TFLOAT|TDOUBLE|TLL|TPOINT, + NAREG|NASL, RESC1, /* should be 0 */ + " pushj 017,(AL)\nZB", }, + +{ UCALL, INAREG, + SNAME|SOREG, TANY, + SANY, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT|TFLOAT|TDOUBLE|TLL|TPOINT, + NAREG, RESC1, /* should be 0 */ + " pushj 017,@AL\nZB", }, + +#ifdef notyet +/* + * INCR can be slightly optimized. + */ +{ INCR, INAREG, + SAREG|SAREG|SNAME|SOREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TPTRTO, + SONE, TANY, + NAREG, RESC1, + " move A1,AL\n" + " ibp AL\n", }, + +/* Fix check of return value */ +{ INCR, FOREFF, + SAREG|SAREG|SNAME|SOREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TPTRTO, + SONE, TANY, + 0, 0, + " ibp AL\n", }, +#endif + +/* + * PLUS operators. + */ +/* Add a value to a char/short pointer */ +{ PLUS, INAREG|INAREG|FOREFF, + SAREG|SAREG|SNAME|SOREG, TPTRTO|TCHAR|TUCHAR|TSHORT|TUSHORT, + SAREG|SAREG, TWORD, + 0, RRIGHT, + " adjbp AR,AL\n", }, + +/* No more search for char/short pointer addition */ +{ PLUS, INAREG|INAREG|FOREFF, + SANY, TPTRTO|TCHAR|TUCHAR|TSHORT|TUSHORT, + SANY, TANY, + REWRITE, 0, + "DIEDIEDIE!\n", }, + +/* Add char/short/int to register */ +{ PLUS, FOREFF|INAREG|INAREG, + SAREG|SAREG, TWORD, + SAREG|SAREG|SNAME|SOREG, TWORD, + 0, RLEFT, + " add AL,AR\n", }, + +/* Add char/short/int to memory */ +{ PLUS, FOREFF|INAREG|INAREG, + SAREG|SAREG|SNAME|SOREG, TWORD, + SAREG|SAREG, TWORD, + 0, RLEFT, + " addm AR,AL\n", }, + +/* Add a small constant to a register */ +{ PLUS, FOREFF|INAREG|INAREG, + SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD|TPOINT, + SUSHCON, TWORD, + 0, RLEFT, + " addi AL,AR\n", }, + +/* Add a larger constant to a register */ +{ PLUS, FOREFF|INAREG|INAREG, + SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD|TPOINT, + SCON, TWORD, + 0, RLEFT, + " add AL,[ .long AR ]\n", }, + +/* Add long long to register */ +{ PLUS, INAREG|INAREG|FOREFF, + SAREG|SAREG, TLL, + SAREG|SAREG|SNAME|SOREG, TLL, + 0, RLEFT, + " dadd AL,AR\n", }, + +/* Add int (or int pointer) to register */ +{ PLUS, FOREFF|INAREG|INAREG, + SAREG|SAREG, TWORD|TPOINT, + SAREG|SAREG|SNAME|SOREG, TWORD, + 0, RLEFT, + " add AL,AR # foo \n", }, + +/* char/short are allowed to be added if they are in registers */ +{ PLUS, INAREG|INAREG|FOREFF, + SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + 0, RLEFT, + " add AL,AR\n", }, + +/* get address of an memory position into a register */ +{ PLUS, INAREG|INAREG, + SAREG|SAREG, TWORD|TPTRTO, + SCON, TANY, + NAREG, RESC1, + " xmovei A1,AR(AL)\n", }, + +/* Safety belt for plus */ +{ PLUS, FORREW|FOREFF|INAREG|INAREG, + SANY, TANY, + SANY, TANY, + REWRITE, 0, + "DIEDIEDIE", }, + +/* + * MINUS operators. + */ +/* Rewrite subtracts from char/short pointers (to negative adds) */ +{ MINUS, FORREW|FOREFF|INAREG|INAREG, + SANY, TCHAR|TUCHAR|TSHORT|TUSHORT|TPTRTO, + SANY, TANY, + REWRITE, 0, + "DIEDIEDIE", }, + +/* Subtract char/short/int word in memory from reg */ +{ MINUS, FOREFF|INAREG|INAREG, + SAREG|SAREG, TWORD|TPOINT, + SAREG|SAREG|SNAME|SOREG, TWORD|TPOINT, + 0, RLEFT, + " sub AL,AR\n", }, + +/* Subtract a small constant from reg */ +{ MINUS, FOREFF|INAREG|INAREG, + SAREG|SAREG, TWORD|TPOINT, + SUSHCON, TWORD|TPOINT, + 0, RLEFT, + " subi AL,AR\n", }, + +/* Subtract a large constant from reg */ +{ MINUS, FOREFF|INAREG|INAREG, + SAREG|SAREG, TWORD|TPOINT, + SCON, TWORD|TPOINT, + 0, RLEFT, + " sub AL,[ .long AR ]\n", }, + +/* Subtract char/short/int word in memory from reg, save in memory */ +{ MINUS, FOREFF|INAREG|INAREG, + SAREG|SAREG, TWORD, + SAREG|SAREG|SNAME|SOREG, TWORD, + 0, RRIGHT, + " subm AL,AR\n", }, + +/* Subtract long long from register */ +{ MINUS, INAREG|INAREG|FOREFF, + SAREG|SAREG, TLL, + SAREG|SAREG|SNAME|SOREG, TLL, + 0, RLEFT, + " dsub AL,AR\n", }, + +/* char/short are allowed to be subtracted if they are in registers */ +{ MINUS, INAREG|INAREG|FOREFF, + SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + 0, RLEFT, + " sub AL,AR\n", }, + +/* Safety belt for plus */ +{ MINUS, FORREW|FOREFF|INAREG|INAREG, + SANY, TANY, + SANY, TANY, + REWRITE, 0, + "DIEDIEDIE", }, + +/* + * AND/OR/ER operators. + * Simpler that the ops above in that they only work on integral types. + */ +/* And char/short/int with integer memory */ +{ AND, FOREFF|INAREG|INAREG, + SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + SAREG|SAREG|SNAME|SOREG, TWORD, + 0, RLEFT, + " and AL,AR\n", }, + +/* And char/short/int with register */ +{ AND, FOREFF|INAREG|INAREG, + SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + 0, RLEFT, + " and AL,AR\n", }, + +/* And char/short/int with small constant */ +{ AND, FOREFF|INAREG|INAREG, + SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + SUSHCON, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + 0, RLEFT, + " andi AL,AR\n", }, + +/* And char/short/int with large constant */ +{ AND, FOREFF|INAREG|INAREG, + SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + SCON, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + 0, RLEFT, + " and AL,[ .long AR ]\n", }, + +/* long long AND */ +{ AND, INAREG|FOREFF, + SAREG|SAREG, TLL, + SAREG|SAREG|SNAME|SOREG, TLL, + 0, RLEFT, + " and AL,AR\n" + " and UL,UR\n", }, + +/* Safety belt for AND */ +{ AND, FORREW|FOREFF|INAREG|INAREG, + SANY, TANY, + SANY, TANY, + REWRITE, 0, + "DIEDIEDIE", }, + + +/* OR char/short/int with integer memory */ +{ OR, FOREFF|INAREG|INAREG, + SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + SAREG|SAREG|SNAME|SOREG, TWORD, + 0, RLEFT, + " ior AL,AR\n", }, + +/* OR char/short/int with register */ +{ OR, FOREFF|INAREG|INAREG, + SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + 0, RLEFT, + " ior AL,AR\n", }, + +/* OR char/short/int with small constant */ +{ OR, FOREFF|INAREG|INAREG, + SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + SUSHCON, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + 0, RLEFT, + " iori AL,AR\n", }, + +/* OR char/short/int with large constant */ +{ OR, FOREFF|INAREG|INAREG, + SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + SCON, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + 0, RLEFT, + " ior AL,[ .long AR ]\n", }, + +/* long long OR */ +{ OR, INAREG|FOREFF, + SAREG|SAREG, TLL, + SAREG|SAREG|SNAME|SOREG, TLL, + 0, RLEFT, + " ior AL,AR\n" + " ior UL,UR\n", }, + +/* Safety belt for OR */ +{ OR, FORREW|FOREFF|INAREG|INAREG, + SANY, TANY, + SANY, TANY, + REWRITE, 0, + "DIEDIEDIE", }, + + +/* ER char/short/int with integer memory */ +{ ER, FOREFF|INAREG|INAREG, + SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + SAREG|SAREG|SNAME|SOREG, TWORD, + 0, RLEFT, + " xor AL,AR\n", }, + +/* ER char/short/int with register */ +{ ER, FOREFF|INAREG|INAREG, + SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + 0, RLEFT, + " xor AL,AR\n", }, + +/* ER char/short/int with small constant */ +{ ER, FOREFF|INAREG|INAREG, + SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + SUSHCON, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + 0, RLEFT, + " xori AL,AR\n", }, + +/* ER char/short/int with large constant */ +{ ER, FOREFF|INAREG|INAREG, + SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + SCON, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD, + 0, RLEFT, + " xor AL,[ .long AR ]\n", }, + +/* long long ER */ +{ ER, INAREG|FOREFF, + SAREG|SAREG, TLL, + SAREG|SAREG|SNAME|SOREG, TLL, + 0, RLEFT, + " xor AL,AR\n" + " xor UL,UR\n", }, + +/* Safety belt for ER */ +{ ER, FORREW|FOREFF|INAREG|INAREG, + SANY, TANY, + SANY, TANY, + REWRITE, 0, + "DIEDIEDIE", }, + +/* + * The next rules handle all shift operators. + */ +{ LS, INAREG|INAREG|FOREFF, + SAREG|SAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT, + SAREG|SAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT, + 0, RLEFT, + " lsh AL,(AR)\n", }, + +{ LS, INAREG|INAREG|FOREFF, + SAREG|SAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT, + SNAME|SOREG, TWORD, + 0, RLEFT, + " lsh AL,@AR\n", }, + +{ LS, INAREG|INAREG|FOREFF, + SAREG|SAREG, TLL, + SCON, TANY, + 0, RLEFT, + " ashc AL,ZH\n", }, + +{ LS, INAREG|INAREG|FOREFF, + SAREG|SAREG, TLL, + SAREG|SAREG /* |SNAME|SOREG */, TANY, + 0, RLEFT, + " ashc AL,(AR)\n", }, + +{ RS, INAREG|INAREG|FOREFF, + SAREG|SAREG, TSWORD, + SCON, TWORD, + 0, RLEFT, + " ash AL,-ZH\n", }, + +{ RS, INAREG|INAREG|FOREFF, + SAREG|SAREG, TUWORD, + SCON, TWORD, + 0, RLEFT, + " lsh AL,-ZH\n", }, + +/* Safety belt for LS/RS */ +{ LS, FORREW|FOREFF|INAREG|INAREG, + SANY, TANY, + SANY, TANY, + REWRITE, 0, + "DIEDIEDIE", }, + +{ RS, FORREW|FOREFF|INAREG|INAREG, + SANY, TANY, + SANY, TANY, + REWRITE, 0, + "DIEDIEDIE", }, + +/* + * The next rules takes care of assignments. "=". + */ +/* Match zeroed registers first */ +{ ASSIGN, INAREG|FOREFF, + SAREG, TUCHAR|TUSHORT|TCHAR|TSHORT|TWORD|TPOINT, + SZERO, TANY, + 0, RDEST, + " setz AL,\n", }, + +{ ASSIGN, FOREFF, + SAREG|SNAME|SOREG, TWORD|TPOINT, + SZERO, TANY, + 0, 0, + " setzm AL\n", }, + +{ ASSIGN, INAREG|FOREFF, + SAREG|SAREG, TUCHAR|TUSHORT|TCHAR|TSHORT|TWORD|TPOINT, + SMONE, TANY, + 0, RDEST, + " setom AL\n", }, + +{ ASSIGN, FOREFF, + SAREG|SNAME|SOREG, TWORD|TPOINT, + SMONE, TANY, + 0, 0, + " setom AL\n", }, + +{ ASSIGN, INAREG|INAREG|FOREFF, + SAREG|SAREG, TWORD|TPOINT, + SCON, TWORD|TPOINT, + 0, RDEST, + " ZC\n", }, + +{ ASSIGN, INAREG|INAREG|FOREFF, + SAREG|SNAME|SOREG, TWORD|TPOINT|TFLOAT, + SAREG|SAREG, TUCHAR|TUSHORT|TWORD|TPOINT|TFLOAT, + 0, RDEST, + " movem AR,AL\n", }, + +{ ASSIGN, INAREG|INAREG|FOREFF, + SAREG|SNAME|SOREG, TWORD|TPOINT|TFLOAT, + SAREG|SAREG, TSHORT, + 0, RDEST, + " hrrem AR,AL\n", }, + +{ ASSIGN, INAREG|INAREG|FOREFF, + SAREG|SAREG, TUCHAR|TUSHORT|TCHAR|TSHORT|TWORD|TPOINT, + SAREG|SAREG|SNAME|SOREG, TWORD|TPOINT, + 0, RDEST, + " move AL,AR\n", }, + +{ ASSIGN, INAREG|INAREG|FOREFF, + SAREG|SAREG, TUCHAR|TUSHORT|TCHAR|TSHORT, + SAREG|SAREG, TUCHAR|TUSHORT|TCHAR|TSHORT, + 0, RDEST, + " move AL,AR\n", }, + +{ ASSIGN, INBREG|FOREFF, + SBREG|SNAME|SOREG, TLL|TDOUBLE, + SBREG, TLL|TDOUBLE, + 0, RDEST, + " dmovem AR,AL\n", }, + +{ ASSIGN, INAREG|INAREG|FOREFF, + SOREG|SNAME, TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG|SAREG, TANY, + 0, RDEST, + "ZV", }, + +{ ASSIGN, INAREG|INAREG|FOREFF, + SAREG|SAREG, TUSHORT|TUCHAR, + SOREG, TANY, + 0, RDEST, + " ldb AL,Zg\n", }, + +{ ASSIGN, INAREG|INAREG|FOREFF, + SAREG|SAREG, TSHORT|TUSHORT|TCHAR|TUCHAR, + SSCON, TANY, + 0, RDEST, + " movei AL,AR\n", }, + +{ ASSIGN, INAREG|INAREG|FOREFF, + SAREG|SAREG, TSHORT|TUSHORT|TCHAR|TUCHAR, + SCON, TANY, + 0, RDEST, + " move AL,[ .long AR]\n", }, + +/* + * DIV/MOD/MUL + * These can be done way more efficient. + */ +/* long long div. XXX - work only with unsigned */ +{ DIV, INBREG, + SBREG|SNAME|SOREG, TLL, + SBREG|SNAME|SOREG, TLL, + (2*NBREG)|NBSL, RESC1, + " dmove A2,AL ; dmove A1,[ .long 0,0 ]\n" + " ddiv A1,AR\n", }, + +/* long long div. with constant. XXX - work only with unsigned */ +{ DIV, INBREG, + SBREG|SNAME|SOREG, TLL, + SCON, TLL, + (2*NBREG)|NBSL, RESC1, + " dmove A2,AL ; dmove A1,[ .long 0,0 ]\n" + " ddiv A1,ZP\n", }, + +/* Simple divide. XXX - fix so next reg can be free */ +{ DIV, INAREG|INAREG|FOREFF, + SAREG|SAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT, + SAREG|SAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT, + 0, RRIGHT, + " idivm AL,AR\n", }, + +/* Safety belt for DIV */ +{ DIV, FORREW|FOREFF|INAREG|INAREG, + SANY, TANY, + SANY, TANY, + REWRITE, 0, + "DIEDIEDIE", }, + +/* long long MOD */ +{ MOD, INBREG, + SBREG|SNAME|SOREG, TLL, + SBREG|SNAME|SOREG, TLL, + 2*NBREG|NBSL, RESC2, + " dmove A2,AL ; dmove A1,[ .long 0,0 ]\n" + " ddiv A1,AR\n", }, + +/* integer MOD */ +{ MOD, INAREG, + SAREG|SNAME|SOREG, TWORD, + SAREG|SNAME|SOREG, TWORD, + 2*NAREG|NASL, RESC2, + " move A2,AL\n" + " setz A1,\n" + " idiv A1,AR\n", }, + +/* integer MOD for char/short */ +{ MOD, INAREG, + SAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT, + SAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT, + 2*NAREG|NASL, RESC2, + " move A2,AL\n" + " setz A1,\n" + " idiv A1,AR\n", }, + +/* Safety belt for MOD */ +{ MOD, FOREFF, + SANY, TANY, + SANY, TANY, + REWRITE, 0, + "DIEDIEDIE", }, + +/* long long MUL */ +{ MUL, INBREG, + SBREG|SNAME|SOREG, TLL, + SBREG|SNAME|SOREG, TLL, + 2*NBREG|NBSL, RESC2, + " dmove A1,AL\n" + " dmul A1,AR\n", }, + +/* integer multiply to memory*/ +{ MUL, INAREG|INAREG|FOREFF, + SAREG|SAREG|SNAME|SOREG, TWORD, + SAREG|SAREG, TWORD, + 0, RLEFT, + " imulm AR,AL\n", }, + +/* integer multiply */ +{ MUL, INAREG|INAREG|FOREFF, + SAREG|SAREG, TWORD, + SAREG|SAREG|SNAME|SOREG, TWORD, + 0, RLEFT, + " imul AL,AR\n", }, + +/* integer multiply for char/short */ +{ MUL, INAREG|INAREG|FOREFF, + SAREG|SAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT, + SAREG|SAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT, + 0, RLEFT, + " imul AL,AR\n", }, + +/* integer multiply with small constant */ +{ MUL, INAREG|INAREG|FOREFF, + SAREG|SAREG, TWORD, + SUSHCON, TWORD, + 0, RLEFT, + " imuli AL,AR\n", }, + +/* integer multiply with large constant */ +{ MUL, INAREG|INAREG|FOREFF, + SAREG|SAREG, TWORD, + SCON, TWORD, + 0, RLEFT, + " imul AL,[ .long AR ]\n", }, + +/* Safety belt for MUL */ +{ MUL, FORREW|FOREFF|INAREG|INAREG, + SANY, TANY, + SANY, TANY, + REWRITE, 0, + "DIEDIEDIE", }, + +/* read an indirect long long value into register */ +{ UMUL, INAREG, + SAREG|SAREG, TPTRTO|TLL|TWORD, + SANY, TLL, + NAREG|NASL, RESC1, + " dmove A1,(AL)\n", }, + +/* read an indirect integer value into register */ +{ UMUL, INAREG, + SAREG|SAREG, TWORD|TPOINT, + SANY, TWORD|TPOINT, + NAREG|NASL, RESC1, + " move A1,(AL)\n", }, + +/* read an indirect value into register */ +{ UMUL, INAREG, + SOREG, TWORD|TPOINT, + SANY, TWORD|TPOINT, + NAREG, RESC1, + " move A1,@AL\n", }, + +/* read an indirect value into register */ +{ UMUL, INAREG, + SAREG|SAREG|SOREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TPTRTO, + SANY, TCHAR|TUCHAR|TSHORT|TUSHORT, + NAREG|NASL, RESC1, + " ldb A1,AL\n", }, + +#ifdef notyet +/* Match tree shape for ildb */ +{ UMUL, INAREG, + SANY, TANY, + SILDB, TUCHAR|TCHAR|TPTRTO, + NAREG, RESC1, + " ildb A1,ZA\n", }, +#endif + +/* Match char/short pointers first, requires special handling */ +{ OPLOG, FORCC, + SAREG|SAREG, TPTRTO|TCHAR|TUCHAR|TSHORT|TUSHORT, + SAREG|SAREG, TPTRTO|TCHAR|TUCHAR|TSHORT|TUSHORT, + 0, RESCC, + "ZZ", }, + +/* Can check anything by just comparing if EQ/NE */ +{ OPLOG, FORCC, + SAREG|SAREG, TWORD|TPOINT|TCHAR|TUCHAR|TSHORT|TUSHORT, + SZERO, TANY, + 0, RESCC, + " jumpZe AL,LC # bu\n", }, + +{ EQ, FORCC, + SAREG|SAREG, TWORD|TPOINT|TCHAR|TUCHAR|TSHORT|TUSHORT, + SAREG|SAREG|SOREG|SNAME|SCON, TWORD|TPOINT, + 0, RESCC, + "ZR", }, + +{ NE, FORCC, + SAREG|SAREG, TWORD|TPOINT|TCHAR|TUCHAR|TSHORT|TUSHORT, + SAREG|SAREG|SOREG|SNAME|SCON, TWORD|TPOINT, + 0, RESCC, + "ZR", }, + +{ OPLOG, FORCC, + SAREG|SAREG, TWORD, + SAREG|SAREG|SOREG|SNAME|SCON, TSWORD, + 0, RESCC, + "ZR", }, + +{ OPLOG, FORCC, + SAREG|SAREG, TCHAR|TUCHAR, + SCON, TANY, + 0, RESCC, + "ZR", }, + +{ OPLOG, FORCC, + SAREG|SAREG, TWORD|TPOINT|TFLOAT, + SAREG|SAREG|SOREG|SNAME|SCON, TWORD|TPOINT|TFLOAT, + 0, RESCC, + "ZR", }, + +{ OPLOG, FORCC, + SAREG|SAREG, TWORD|TPOINT|TCHAR|TUCHAR|TSHORT|TUSHORT, + SAREG|SAREG, TWORD|TPOINT|TCHAR|TUCHAR|TSHORT|TUSHORT, + 0, RESCC, + "ZR", }, + +{ OPLOG, FORCC, + SAREG|SAREG, TLL|TDOUBLE, /* XXX - does double work here? */ + SAREG|SAREG|SOREG|SNAME, TLL|TDOUBLE, + 0, RESCC, + "ZQ", }, + +/* + * Jumps. + */ +{ GOTO, FOREFF, + SCON, TANY, + SANY, TANY, + 0, RNOP, + " jrst LL\n", }, + +/* + * Convert LTYPE to reg. + */ +{ OPLTYPE, INBREG, + SANY, TANY, + SMONE, TLL, + NBREG, RESC1, + " seto A1,\n seto U1,\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SMONE, TANY, + NAREG, RESC1, + " seto A1,\n", }, + +{ OPLTYPE, INBREG, + SANY, TANY, + SZERO, TLL, + NBREG, RESC1, + " setz A1,\n setz U1,\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SZERO, TANY, + NAREG, RESC1, + " setz A1,\n", }, + +{ OPLTYPE, INBREG, + SANY, TANY, + SUSHCON, TLL, + NBREG, RESC1, + " setz A1,\n movei U1,AR\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SUSHCON, ANYFIXED, + NAREG, RESC1, + " movei A1,AR\n", }, + +{ OPLTYPE, INAREG, + SANY, ANYFIXED, + SNSHCON, ANYFIXED, + NAREG, RESC1, + " hrroi A1,AR\n", }, + +{ OPLTYPE, INAREG, + SANY, ANYFIXED, + SCON, ANYFIXED, + NAREG|NASR, RESC1, + " ZD A1,ZE # suspekt\n", }, + +{ OPLTYPE, INAREG, + SANY, TWORD|TPOINT|TFLOAT, + SAREG|SAREG|SOREG|SNAME, TWORD|TPOINT|TFLOAT, + NAREG|NASR, RESC1, + " move A1,AR\n", }, + +{ OPLTYPE, INBREG, + SANY, TLL, + SCON, TLL, + NBREG, RESC1, + " dmove A1,ZO\n", }, + +{ OPLTYPE, INBREG, + SANY, TLL|TDOUBLE, + SANY, TLL|TDOUBLE, + NBREG|NBSR, RESC1, + " dmove A1,AR\n", }, + +{ OPLTYPE, INAREG, + SOREG, TSHORT|TUSHORT|TCHAR|TUCHAR, + SOREG, TSHORT|TUSHORT|TCHAR|TUCHAR, + NASR, RESC1, + "ZU", }, + +{ OPLTYPE, INAREG, + SNAME, TUCHAR, + SNAME, TUCHAR, + NAREG|NASR, RESC1, + " ldb A1,[ .long AL ]\n" }, + +{ OPLTYPE, INAREG, + SNAME, TCHAR, + SNAME, TCHAR, + NAREG|NASR, RESC1, + " ldb A1,[ .long AL ]\n" + " ash A1,033\n" + " ash A1,-033\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SNAME, TSHORT|TUSHORT, + NAREG|NASR, RESC1, + "Zi", }, + +{ OPLTYPE, INAREG, + SANY, TWORD|TPOINT, + SCON, TWORD|TPOINT, + NAREG|NASR, RESC1, + "Zc", }, + +{ OPLTYPE, INAREG, + SAREG|SAREG, TUSHORT|TUCHAR, + SAREG|SAREG, TUSHORT|TUCHAR|TWORD, + NAREG, RESC1, + " move A1,AL\n", }, + +/* + * Negate a word. + */ +{ UMINUS, INAREG, + SAREG|SAREG|SNAME|SOREG, TWORD, + SANY, TWORD, + NAREG|NASL, RESC1, + " movn A1,AL\n", }, + +{ UMINUS, INAREG, + SAREG|SAREG, TWORD, + SANY, TCHAR|TUCHAR|TSHORT|TUSHORT, + 0, RLEFT, + " movn AL,AL\n", }, + +{ UMINUS, INAREG, + SAREG|SNAME|SOREG, TLL, + SANY, TLL, + NAREG|NASR, RESC1, + " dmovn A1,AL\n", }, + +{ COMPL, INAREG, + SAREG|SAREG|SNAME|SOREG, TLL, + SANY, TANY, + NAREG|NASL, RESC1, + " setcm A1,AL\n" + " setcm U1,UL\n", }, + +{ COMPL, INAREG, + SAREG|SAREG|SNAME|SOREG, TWORD, + SANY, TANY, + NAREG|NASL, RESC1, + " setcm A1,AL\n", }, + +{ COMPL, INAREG, + SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT, + SANY, TCHAR|TUCHAR|TSHORT|TUSHORT, + NAREG|NASL, RESC1, + " setcm A1,AL\n", }, + +/* + * Arguments to functions. + */ +{ FUNARG, FOREFF, + SAREG|SNAME|SOREG, TWORD|TPOINT|TFLOAT, + SANY, TANY, + 0, RNULL, + " push 017,AL\n", }, + +{ FUNARG, FOREFF, + SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT, + SANY, TANY, + 0, RNULL, + " push 017,AL\n", }, + +{ FUNARG, FOREFF, + SCON, TCHAR|TUCHAR|TSHORT|TUSHORT|TPOINT|TWORD, + SANY, TANY, + 0, RNULL, + " push 017,[ .long AL]\n", }, + +{ FUNARG, FOREFF, + SBREG, TLL|TDOUBLE, + SANY, TANY, + 0, RNULL, + " push 017,AL\n push 017,UL\n", }, + +{ STARG, FOREFF, + SAREG|SOREG|SNAME|SCON, TANY, + SANY, TSTRUCT, + 0, 0, + "ZG", }, + + +# define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,"" + +{ UMUL, DF( UMUL ), }, + +{ ASSIGN, DF(ASSIGN), }, + +{ OPLEAF, DF(NAME), }, + +{ OPUNARY, DF(UMINUS), }, + +{ FREE, FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" }, +}; + +int tablesize = sizeof(table)/sizeof(table[0]); diff --git a/compilers/pcc/pcc-1.0.0/arch/pdp11/CVS/Entries b/compilers/pcc/pcc-1.0.0/arch/pdp11/CVS/Entries new file mode 100644 index 00000000..fd922585 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/pdp11/CVS/Entries @@ -0,0 +1,7 @@ +/code.c/1.3/Sun Feb 8 16:41:35 2009//Tr-1-0-0-RELEASE +/local.c/1.7/Fri Jan 21 21:47:58 2011//Tr-1-0-0-RELEASE +/local2.c/1.8/Wed Jul 29 12:34:19 2009//Tr-1-0-0-RELEASE +/macdefs.h/1.4/Sat Jan 24 21:43:49 2009//Tr-1-0-0-RELEASE +/order.c/1.3/Sat Oct 4 08:43:17 2008//Tr-1-0-0-RELEASE +/table.c/1.5/Sun Oct 19 15:25:25 2008//Tr-1-0-0-RELEASE +D diff --git a/compilers/pcc/pcc-1.0.0/arch/pdp11/CVS/Repository b/compilers/pcc/pcc-1.0.0/arch/pdp11/CVS/Repository new file mode 100644 index 00000000..b44ae113 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/pdp11/CVS/Repository @@ -0,0 +1 @@ +pcc/arch/pdp11 diff --git a/compilers/pcc/pcc-1.0.0/arch/pdp11/CVS/Root b/compilers/pcc/pcc-1.0.0/arch/pdp11/CVS/Root new file mode 100644 index 00000000..71e2ccb9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/pdp11/CVS/Root @@ -0,0 +1 @@ +/cvsroot diff --git a/compilers/pcc/pcc-1.0.0/arch/pdp11/CVS/Tag b/compilers/pcc/pcc-1.0.0/arch/pdp11/CVS/Tag new file mode 100644 index 00000000..060fac05 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/pdp11/CVS/Tag @@ -0,0 +1 @@ +Nr-1-0-0-RELEASE diff --git a/compilers/pcc/pcc-1.0.0/arch/pdp11/code.c b/compilers/pcc/pcc-1.0.0/arch/pdp11/code.c new file mode 100644 index 00000000..f16e32dd --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/pdp11/code.c @@ -0,0 +1,197 @@ +/* $Id: code.c,v 1.3 2009/02/08 16:41:35 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass1.h" + +int lastloc = -1; + +/* + * Define everything needed to print out some data (or text). + * This means segment, alignment, visibility, etc. + */ +void +defloc(struct symtab *sp) +{ + static char *loctbl[] = { "text", "data", "data" }; + TWORD t; + char *n; + int s; + + if (sp == NULL) { + lastloc = -1; + return; + } + t = sp->stype; + s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA; + if (s != lastloc) + printf(" .%s\n", loctbl[s]); + lastloc = s; + while (ISARY(t)) + t = DECREF(t); + n = sp->soname ? sp->soname : exname(sp->sname); + if (sp->sclass == EXTDEF) + printf(" .globl %s\n", n); + if (ISFTN(sp->stype) || talign(sp->stype, sp->ssue) > ALCHAR) + printf(".even\n"); + if (sp->slevel == 0) { + printf("%s:\n", n); + } else { + printf(LABFMT ":\n", sp->soffset); + } +} + +/* + * code for the end of a function + * deals with struct return here + */ +void +efcode() +{ + NODE *p, *q; + + if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) + return; + /* Create struct assignment */ + q = block(OREG, NIL, NIL, PTR+STRTY, 0, cftnsp->ssue); + q->n_rval = R5; + q->n_lval = 8; /* return buffer offset */ + q = buildtree(UMUL, q, NIL); + p = block(REG, NIL, NIL, PTR+STRTY, 0, cftnsp->ssue); + p = buildtree(UMUL, p, NIL); + p = buildtree(ASSIGN, q, p); + ecomp(p); +} + +/* + * code for the beginning of a function; a is an array of + * indices in symtab for the arguments; n is the number + */ +void +bfcode(struct symtab **sp, int cnt) +{ + struct symtab *sp2; + NODE *n; + int i; + + if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) { + /* Function returns struct, adjust arg offset */ + for (i = 0; i < cnt; i++) + sp[i]->soffset += SZPOINT(INT); + } + + if (xtemps == 0) + return; + + /* put arguments in temporaries */ + for (i = 0; i < cnt; i++) { + if (sp[i]->stype == STRTY || sp[i]->stype == UNIONTY || + cisreg(sp[i]->stype) == 0) + continue; + sp2 = sp[i]; + n = tempnode(0, sp[i]->stype, sp[i]->sdf, sp[i]->ssue); + n = buildtree(ASSIGN, n, nametree(sp2)); + sp[i]->soffset = regno(n->n_left); + sp[i]->sflags |= STNODE; + ecomp(n); + } +} + + +/* + * by now, the automatics and register variables are allocated + */ +void +bccode() +{ + SETOFF(autooff, SZINT); +} + +/* called just before final exit */ +/* flag is 1 if errors, 0 if none */ +void +ejobcode(int flag ) +{ +} + +void +bjobcode() +{ +} + +/* + * Called with a function call with arguments as argument. + * This is done early in buildtree() and only done once. + * Returns p. + */ +NODE * +funcode(NODE *p) +{ + NODE *r, *l; + + /* Fix function call arguments. On x86, just add funarg */ + for (r = p->n_right; r->n_op == CM; r = r->n_left) { + if (r->n_right->n_op != STARG) + r->n_right = block(FUNARG, r->n_right, NIL, + r->n_right->n_type, r->n_right->n_df, + r->n_right->n_sue); + } + if (r->n_op != STARG) { + l = talloc(); + *l = *r; + r->n_op = FUNARG; + r->n_left = l; + r->n_type = l->n_type; + } + return p; +} + +/* + * return the alignment of field of type t + */ +int +fldal(unsigned int t) +{ + uerror("illegal field type"); + return(ALINT); +} + +/* fix up type of field p */ +void +fldty(struct symtab *p) +{ +} + +/* + * XXX - fix genswitch. + */ +int +mygenswitch(int num, TWORD type, struct swents **p, int n) +{ + return 0; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/pdp11/local.c b/compilers/pcc/pcc-1.0.0/arch/pdp11/local.c new file mode 100644 index 00000000..10806c51 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/pdp11/local.c @@ -0,0 +1,658 @@ +/* $Id: local.c,v 1.7 2011/01/21 21:47:58 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "pass1.h" + +/* this file contains code which is dependent on the target machine */ + +/* clocal() is called to do local transformations on + * an expression tree preparitory to its being + * written out in intermediate code. + * + * the major essential job is rewriting the + * automatic variables and arguments in terms of + * REG and OREG nodes + * conversion ops which are not necessary are also clobbered here + * in addition, any special features (such as rewriting + * exclusive or) are easily handled here as well + */ +NODE * +clocal(NODE *p) +{ + + register struct symtab *q; + register NODE *r, *l; + register int o; + int m; + +#ifdef PCC_DEBUG + if (xdebug) { + printf("clocal: %p\n", p); + fwalk(p, eprint, 0); + } +#endif + switch( o = p->n_op ){ + + case NAME: + if ((q = p->n_sp) == NULL) + return p; /* Nothing to care about */ + + switch (q->sclass) { + + case PARAM: + case AUTO: + /* fake up a structure reference */ + r = block(REG, NIL, NIL, PTR+STRTY, 0, 0); + r->n_lval = 0; + r->n_rval = FPREG; + p = stref(block(STREF, r, p, 0, 0, 0)); + break; + + case STATIC: + if (q->slevel == 0) + break; + p->n_lval = 0; + break; + + case REGISTER: + p->n_op = REG; + p->n_lval = 0; + p->n_rval = q->soffset; + break; + + case EXTERN: + case EXTDEF: + break; + } + break; + + case PCONV: + /* Remove redundant PCONV's. Be careful */ + l = p->n_left; + if (l->n_op == ICON) { + l->n_lval = (unsigned)l->n_lval; + goto delp; + } + if (l->n_type < INT || l->n_type == LONGLONG || + l->n_type == ULONGLONG) { + /* float etc? */ + p->n_left = block(SCONV, l, NIL, + UNSIGNED, 0, MKSUE(UNSIGNED)); + break; + } + /* if left is SCONV, cannot remove */ + if (l->n_op == SCONV) + break; + + /* avoid ADDROF TEMP */ + if (l->n_op == ADDROF && l->n_left->n_op == TEMP) + break; + + /* if conversion to another pointer type, just remove */ + if (p->n_type > BTMASK && l->n_type > BTMASK) + goto delp; + break; + + delp: l->n_type = p->n_type; + l->n_qual = p->n_qual; + l->n_df = p->n_df; + l->n_sue = p->n_sue; + nfree(p); + p = l; + break; + + case SCONV: + l = p->n_left; + +#if 0 + if (p->n_type == l->n_type) { + nfree(p); + return l; + } + + if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 && + btdims[p->n_type].suesize == btdims[l->n_type].suesize) { + if (p->n_type != FLOAT && p->n_type != DOUBLE && + l->n_type != FLOAT && l->n_type != DOUBLE && + l->n_type != LDOUBLE && p->n_type != LDOUBLE) { + if (l->n_op == NAME || l->n_op == UMUL || + l->n_op == TEMP) { + l->n_type = p->n_type; + nfree(p); + return l; + } + } + } + + if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT && + coptype(l->n_op) == BITYPE) { + l->n_type = p->n_type; + nfree(p); + return l; + } +#endif + o = l->n_op; + m = p->n_type; + + if (o == ICON) { + CONSZ val = l->n_lval; + + if (!ISPTR(m)) /* Pointers don't need to be conv'd */ + switch (m) { + case BOOL: + l->n_lval = l->n_lval != 0; + break; + case CHAR: + l->n_lval = (char)val; + break; + case UCHAR: + l->n_lval = val & 0377; + break; + case INT: + l->n_lval = (short)val; + break; + case UNSIGNED: + l->n_lval = val & 0177777; + break; + case ULONG: + l->n_lval = val & 0xffffffff; + break; + case LONG: + l->n_lval = (long)val; + break; + case LONGLONG: + l->n_lval = (long long)val; + break; + case ULONGLONG: + l->n_lval = val; + break; + case VOID: + break; + case LDOUBLE: + case DOUBLE: + case FLOAT: + l->n_op = FCON; + l->n_dcon = FLOAT_CAST(val, l->n_type); + break; + default: + cerror("unknown type %d", m); + } + l->n_type = m; + l->n_sue = MKSUE(m); + nfree(p); + return l; + } else if (l->n_op == FCON) { + l->n_lval = FLOAT_VAL(l->n_dcon); + l->n_sp = NULL; + l->n_op = ICON; + l->n_type = m; + l->n_sue = MKSUE(m); + nfree(p); + return clocal(l); + } + if (DEUNSIGN(p->n_type) == INT && + DEUNSIGN(l->n_type) == INT) { + nfree(p); + p = l; + } + break; + + case CBRANCH: + l = p->n_left; + if (coptype(l->n_op) != BITYPE) + break; + if (l->n_left->n_op != SCONV || l->n_right->n_op != ICON) + break; + if ((r = l->n_left->n_left)->n_type > INT) + break; + /* compare with constant without casting */ + nfree(l->n_left); + l->n_left = r; + l->n_right->n_type = l->n_left->n_type; + break; + + case STASG: /* struct assignment, modify left */ + l = p->n_left; + if (l->n_type == STRTY) + p->n_left = buildtree(ADDROF, l, NIL); + break; + + case PMCONV: + case PVCONV: + r = p; + p = buildtree(o == PMCONV ? MUL : DIV, p->n_left, p->n_right); + nfree(r); + break; + + case FORCE: + /* put return value in return reg */ + p->n_op = ASSIGN; + p->n_right = p->n_left; + p->n_left = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT)); + p->n_left->n_rval = p->n_left->n_type == BOOL ? + RETREG(CHAR) : RETREG(p->n_type); + break; + + } +#ifdef PCC_DEBUG + if (xdebug) { + printf("clocal end: %p\n", p); + fwalk(p, eprint, 0); + } +#endif + return(p); +} + +void +myp2tree(NODE *p) +{ + struct symtab *sp; + + if (p->n_op != FCON) + return; + + sp = inlalloc(sizeof(struct symtab)); + sp->sclass = STATIC; + sp->ssue = MKSUE(p->n_type); + sp->slevel = 1; /* fake numeric label */ + sp->soffset = getlab(); + sp->sflags = 0; + sp->stype = p->n_type; + sp->squal = (CON >> TSHIFT); + + defloc(sp); + ninval(0, sp->ssue->suesize, p); + + p->n_op = NAME; + p->n_lval = 0; + p->n_sp = sp; +} + +/*ARGSUSED*/ +int +andable(NODE *p) +{ + return(1); /* all names can have & taken on them */ +} + +/* + * at the end of the arguments of a ftn, set the automatic offset + */ +void +cendarg() +{ + autooff = AUTOINIT; +} + +/* + * Return 1 if a variable of type type is OK to put in register. + */ +int +cisreg(TWORD t) +{ + if (t == FLOAT || t == DOUBLE || t == LDOUBLE || + t == LONGLONG || t == ULONGLONG) + return 0; /* not yet */ + return 1; +} + +/* + * return a node, for structure references, which is suitable for + * being added to a pointer of type t, in order to be off bits offset + * into a structure + * t, d, and s are the type, dimension offset, and sizeoffset + * For pdp10, return the type-specific index number which calculation + * is based on its size. For example, short a[3] would return 3. + * Be careful about only handling first-level pointers, the following + * indirections must be fullword. + */ +NODE * +offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue) +{ + register NODE *p; + + if (xdebug) + printf("offcon: OFFSZ %lld type %x dim %p siz %d\n", + off, t, d, sue->suesize); + + p = bcon(0); + p->n_lval = off/SZCHAR; /* Default */ + return(p); +} + +/* + * Allocate off bits on the stack. p is a tree that when evaluated + * is the multiply count for off, t is a storeable node where to write + * the allocated address. + */ +void +spalloc(NODE *t, NODE *p, OFFSZ off) +{ + NODE *sp; + + p = buildtree(MUL, p, bcon(off/SZCHAR)); /* XXX word alignment? */ + + /* sub the size from sp */ + sp = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT)); + sp->n_lval = 0; + sp->n_rval = STKREG; + ecomp(buildtree(MINUSEQ, sp, p)); + + /* save the address of sp */ + sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_sue); + sp->n_lval = 0; + sp->n_rval = STKREG; + t->n_type = sp->n_type; + ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */ + +} + +/* + * Print out a string of characters. + * Assume that the assembler understands C-style escape + * sequences. + */ +void +instring(struct symtab *sp) +{ + char *s; + int val, cnt; + + defloc(sp); + + for (cnt = 0, s = sp->sname; *s != 0; ) { + if (cnt++ == 0) + printf(".byte "); + if (*s++ == '\\') + val = esccon(&s); + else + val = s[-1]; + printf("%o", val & 0377); + if (cnt > 15) { + cnt = 0; + printf("\n"); + } else + printf(","); + } + printf("%s0\n", cnt ? "" : ".byte "); +} + +static int inbits, inval; + +/* + * set fsz bits in sequence to zero. + */ +void +zbits(OFFSZ off, int fsz) +{ + int m; + + if (idebug) + printf("zbits off %lld, fsz %d inbits %d\n", off, fsz, inbits); + if ((m = (inbits % SZCHAR))) { + m = SZCHAR - m; + if (fsz < m) { + inbits += fsz; + return; + } else { + fsz -= m; + printf("\t.byte %d\n", inval); + inval = inbits = 0; + } + } + if (fsz >= SZCHAR) { + printf(".=.+%o\n", fsz/SZCHAR); + fsz -= (fsz/SZCHAR) * SZCHAR; + } + if (fsz) { + inval = 0; + inbits = fsz; + } +} + +/* + * Initialize a bitfield. + */ +void +infld(CONSZ off, int fsz, CONSZ val) +{ + if (idebug) + printf("infld off %lld, fsz %d, val %lld inbits %d\n", + off, fsz, val, inbits); + val &= ((CONSZ)1 << fsz)-1; + while (fsz + inbits >= SZCHAR) { + inval |= (val << inbits); + printf("\t.byte %d\n", inval & 255); + fsz -= (SZCHAR - inbits); + val >>= (SZCHAR - inbits); + inval = inbits = 0; + } + if (fsz) { + inval |= (val << inbits); + inbits += fsz; + } +} + +/* + * print out a constant node, may be associated with a label. + * Do not free the node after use. + * off is bit offset from the beginning of the aggregate + * fsz is the number of bits this is referring to + */ +void +ninval(CONSZ off, int fsz, NODE *p) +{ +#ifdef __pdp11__ + union { float f; double d; short s[4]; int i[2]; } u; +#endif + struct symtab *q; + TWORD t; + int i; + + t = p->n_type; + if (t > BTMASK) + t = INT; /* pointer */ + + while (p->n_op == SCONV || p->n_op == PCONV) { + NODE *l = p->n_left; + l->n_type = p->n_type; + p = l; + } + + if (p->n_op != ICON && p->n_op != FCON) + cerror("ninval: init node not constant"); + + if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT) + uerror("element not constant"); + + switch (t) { + case LONGLONG: + case ULONGLONG: + i = (p->n_lval >> 32); + p->n_lval &= 0xffffffff; + p->n_type = INT; + ninval(off, 32, p); + p->n_lval = i; + ninval(off+32, 32, p); + break; + case LONG: + case ULONG: + printf("%o ; %o\n", (int)((p->n_lval >> 16) & 0177777), + (int)(p->n_lval & 0177777)); + break; + case INT: + case UNSIGNED: + printf("%o", (int)(p->n_lval & 0177777)); + if ((q = p->n_sp) != NULL) { + if ((q->sclass == STATIC && q->slevel > 0)) { + printf("+" LABFMT, q->soffset); + } else { + printf("+%s", q->soname ? q->soname : exname(q->sname)); + } + } + printf("\n"); + break; + case BOOL: + if (p->n_lval > 1) + p->n_lval = p->n_lval != 0; + /* FALLTHROUGH */ + case CHAR: + case UCHAR: + printf("\t.byte %o\n", (int)p->n_lval & 0xff); + break; +#ifdef __pdp11__ + case FLOAT: + u.f = (float)p->n_dcon; + printf("%o ; %o\n", u.i[0], u.i[1]); + break; + case LDOUBLE: + case DOUBLE: + u.d = (double)p->n_dcon; + printf("%o ; %o ; %o ; %o\n", u.i[0], u.i[1], u.i[2], u.i[3]); + break; +#else + /* cross-compiling */ + case FLOAT: + printf("%o ; %o\n", p->n_dcon.fd1, p->n_dcon.fd2); + break; + case LDOUBLE: + case DOUBLE: + printf("%o ; %o ; %o ; %o\n", p->n_dcon.fd1, p->n_dcon.fd2, + p->n_dcon.fd3, p->n_dcon.fd4); + break; +#endif + default: + cerror("ninval"); + } +} + +/* make a name look like an external name in the local machine */ +char * +exname(char *p) +{ +#define NCHNAM 256 + static char text[NCHNAM+1]; + int i; + + if (p == NULL) + return ""; + + text[0] = '_'; + for (i=1; *p && istype, sp->sdf, sp->ssue); + off = (off+(SZCHAR-1))/SZCHAR; + n = sp->soname ? sp->soname : exname(sp->sname); + if (sp->sclass == STATIC) { + printf(".bss\n"); + if (sp->slevel == 0) + printf("%s:", n); + else + printf(LABFMT ":", sp->soffset); + printf(" .=.+%o\n", off); + lastloc = -1; + return; + } + printf(".comm "); + if (sp->slevel == 0) + printf("%s,0%o\n", n, off); + else + printf(LABFMT ",0%o\n", sp->soffset, off); +} + +/* + * Give target the opportunity of handling pragmas. + */ +int +mypragma(char *str) +{ + return 0; +} + +/* + * Called when a identifier has been declared. + */ +void +fixdef(struct symtab *sp) +{ +} + +void +pass1_lastchance(struct interpass *ip) +{ +} diff --git a/compilers/pcc/pcc-1.0.0/arch/pdp11/local2.c b/compilers/pcc/pcc-1.0.0/arch/pdp11/local2.c new file mode 100644 index 00000000..279cb7ac --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/pdp11/local2.c @@ -0,0 +1,845 @@ +/* $Id: local2.c,v 1.8 2009/07/29 12:34:19 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +# include "pass2.h" +# include +# include + +static int spcoff; +static int argsiz(NODE *p); + +void +deflab(int label) +{ + printf(LABFMT ":\n", label); +} + +void +prologue(struct interpass_prolog *ipp) +{ + int addto; + +#ifdef LANG_F77 + if (ipp->ipp_vis) + printf(" .globl %s\n", ipp->ipp_name); + printf("%s:\n", ipp->ipp_name); +#endif + printf("jsr r5,csv\n"); + addto = p2maxautooff; + if (addto >= AUTOINIT/SZCHAR) + addto -= AUTOINIT/SZCHAR; + if (addto & 1) + addto++; + if (addto == 2) + printf("tst -(sp)\n"); + else if (addto == 4) + printf("cmp -(sp),-(sp)\n"); + else if (addto > 4) + printf("sub $%o,sp\n", addto); + spcoff = 0; +} + +void +eoftn(struct interpass_prolog *ipp) +{ + if (spcoff) + comperr("spcoff == %d", spcoff); + if (ipp->ipp_ip.ip_lbl == 0) + return; /* no code needs to be generated */ + printf("jmp cret\n"); +} + +/* + * add/sub/... + * + * Param given: + */ +void +hopcode(int f, int o) +{ + char *str; + + switch (o) { + case PLUS: + str = "add"; + break; + case MINUS: + str = "sub"; + break; + case AND: + str = "and"; + break; + case OR: + str = "or"; + break; + case ER: + str = "xor"; + break; + default: + comperr("hopcode2: %d", o); + str = 0; /* XXX gcc */ + } + printf("%s%c", str, f); +} + +/* + * Return type size in bytes. Used by R2REGS, arg 2 to offset(). + */ +int +tlen(p) NODE *p; +{ + switch(p->n_type) { + case CHAR: + case UCHAR: + return(1); + + case SHORT: + case USHORT: + return(SZSHORT/SZCHAR); + + case DOUBLE: + return(SZDOUBLE/SZCHAR); + + case INT: + case UNSIGNED: + case LONG: + case ULONG: + return(SZINT/SZCHAR); + + case LONGLONG: + case ULONGLONG: + return SZLONGLONG/SZCHAR; + + default: + if (!ISPTR(p->n_type)) + comperr("tlen type %d not pointer"); + return SZPOINT(p->n_type)/SZCHAR; + } +} + +/* + * Emit code to compare two long numbers. + */ +static void +twolcomp(NODE *p) +{ + int o = p->n_op; + int s = getlab2(); + int e = p->n_label; + int cb1, cb2; + + if (o >= ULE) + o -= (ULE-LE); + switch (o) { + case NE: + cb1 = 0; + cb2 = NE; + break; + case EQ: + cb1 = NE; + cb2 = 0; + break; + case LE: + case LT: + cb1 = GT; + cb2 = LT; + break; + case GE: + case GT: + cb1 = LT; + cb2 = GT; + break; + + default: + cb1 = cb2 = 0; /* XXX gcc */ + } + if (p->n_op >= ULE) + cb1 += 2, cb2 += 2; + expand(p, 0, "cmp AR,AL\n"); + if (cb1) cbgen(cb1, s); + if (cb2) cbgen(cb2, e); + expand(p, 0, "cmp UR,UL\n"); + cbgen(p->n_op, e); + deflab(s); +} + + +/* + * Generate compare code for long instructions when right node is 0. + */ +static void +lcomp(NODE *p) +{ + switch (p->n_op) { + case EQ: + expand(p, FORCC, "tst AL\n"); + printf("jne 1f\n"); + expand(p, FORCC, "tst UL\n"); + cbgen(EQ, p->n_label); + printf("1:\n"); + break; + case NE: + expand(p, FORCC, "tst AL\n"); + cbgen(NE, p->n_label); + expand(p, FORCC, "tst UL\n"); + cbgen(NE, p->n_label); + break; + case GE: + expand(p, FORCC, "tst AL\n"); + cbgen(GE, p->n_label); + break; + default: + comperr("lcomp %p", p); + } +} + +void +zzzcode(NODE *p, int c) +{ + switch (c) { + case 'A': /* print out - if not first arg */ + if (spcoff || (p->n_type == FLOAT || p->n_type == DOUBLE)) + printf("-"); + spcoff += argsiz(p); + break; + + case 'B': /* arg is pointer to block */ + expand(p->n_left, FOREFF, "mov AL,ZA(sp)\n"); + expand(p->n_left, FOREFF, "sub CR,(sp)\n"); + break; + + case 'C': /* subtract stack after call */ + spcoff -= p->n_qual; + if (spcoff == 0 && !(p->n_flags & NLOCAL1)) + p->n_qual -= 2; + if (p->n_qual == 2) + printf("tst (sp)+\n"); + else if (p->n_qual == 4) + printf("cmp (sp)+,(sp)+\n"); + else if (p->n_qual > 2) + printf("add $%o,sp\n", (int)p->n_qual); + break; + + case 'D': /* long comparisions */ + lcomp(p); + break; + + case 'E': /* long move */ + rmove(p->n_right->n_reg, p->n_left->n_reg, p->n_type); + break; + + case 'F': /* long comparision */ + twolcomp(p); + break; + + case 'G': /* printout a subnode for post-inc */ + adrput(stdout, p->n_left->n_left); + break; + + case 'H': /* arg with post-inc */ + expand(p->n_left->n_left, FOREFF, "mov AL,ZA(sp)\n"); + expand(p->n_left->n_left, FOREFF, "inc AL\n"); + break; + + case 'Q': /* struct assignment, no rv */ + printf("mov $%o,", p->n_stsize/2); + expand(p, INAREG, "A1\n"); + printf("1:\n"); + expand(p, INAREG, "mov (AR)+,(AL)+\n"); + expand(p, INAREG, "dec A1\n"); + printf("jne 1b\n"); + break; + + case 'R': /* struct assignment with rv */ + printf("mov $%o,", p->n_stsize/2); + expand(p, INAREG, "A1\n"); + expand(p, INAREG, "mov AR,A2\n"); + printf("1:\n"); + expand(p, INAREG, "mov (A2)+,(AL)+\n"); + expand(p, INAREG, "dec A1\n"); + printf("jne 1b\n"); + break; + + case '1': /* lower part of double regs */ + p = getlr(p, '1'); + printf("r%c", rnames[p->n_rval][1]); + break; + + default: + comperr("zzzcode %c", c); + } +} + +/*ARGSUSED*/ +int +rewfld(NODE *p) +{ + return(1); +} + +int canaddr(NODE *); +int +canaddr(NODE *p) +{ + int o = p->n_op; + + if (o==NAME || o==REG || o==ICON || o==OREG || + (o==UMUL && shumul(p->n_left, STARNM|SOREG))) + return(1); + return(0); +} + +/* + * Does the bitfield shape match? + */ +int +flshape(NODE *p) +{ + int o = p->n_op; + + if (o == OREG || o == REG || o == NAME) + return SRDIR; /* Direct match */ + if (o == UMUL && shumul(p->n_left, SOREG)) + return SROREG; /* Convert into oreg */ + return SRREG; /* put it into a register */ +} + +/* INTEMP shapes must not contain any temporary registers */ +/* XXX should this go away now? */ +int +shtemp(NODE *p) +{ + return 0; +#if 0 + int r; + + if (p->n_op == STARG ) + p = p->n_left; + + switch (p->n_op) { + case REG: + return (!istreg(p->n_rval)); + + case OREG: + r = p->n_rval; + if (R2TEST(r)) { + if (istreg(R2UPK1(r))) + return(0); + r = R2UPK2(r); + } + return (!istreg(r)); + + case UMUL: + p = p->n_left; + return (p->n_op != UMUL && shtemp(p)); + } + + if (optype(p->n_op) != LTYPE) + return(0); + return(1); +#endif +} + +static void +negcon(FILE *fp, int con) +{ + if (con < 0) + fprintf(fp, "-"), con = -con; + fprintf(fp, "%o", con & 0177777); +} + +void +adrcon(CONSZ val) +{ + printf("$" CONFMT, val); +} + +void +conput(FILE *fp, NODE *p) +{ + int val = p->n_lval; + + switch (p->n_op) { + case ICON: + printf("$"); + if (p->n_name[0] != '\0') { + fprintf(fp, "%s", p->n_name); + if (val) + fprintf(fp, "+%o", val & 0177777); + } else if (p->n_type == LONG || p->n_type == ULONG) + negcon(fp, val >> 16); + else + negcon(fp, val); + return; + + default: + comperr("illegal conput, p %p", p); + } +} + +/*ARGSUSED*/ +void +insput(NODE *p) +{ + comperr("insput"); +} + +/* + * Write out the upper address, like the upper register of a 2-register + * reference, or the next memory location. + */ +void +upput(NODE *p, int size) +{ + size /= SZINT; + switch (p->n_op) { + case NAME: + case OREG: + p->n_lval += size; + adrput(stdout, p); + p->n_lval -= size; + break; + case REG: + printf("r%c", rnames[p->n_rval][2]); + break; + case ICON: + /* On PDP11 upper value is low 16 bits */ + printf("$"); + negcon(stdout, p->n_lval & 0177777); + break; + default: + comperr("upput bad op %d size %d", p->n_op, size); + } +} + +/* + * output an address, with offsets, from p + */ +void +adrput(FILE *io, NODE *p) +{ + int r; + + if (p->n_op == FLD) + p = p->n_left; + + switch (p->n_op) { + case NAME: + if (p->n_name[0] != '\0') { + fputs(p->n_name, io); + if (p->n_lval != 0) + fprintf(io, "+%o", (int)(p->n_lval&0177777)); + } else + negcon(io, p->n_lval); + return; + + case OREG: + r = p->n_rval; + if (p->n_name[0]) + printf("%s%s", p->n_name, p->n_lval ? "+" : ""); + if (R2TEST(r) && R2UPK3(r) == 0) + printf("*"); + if (p->n_lval) + negcon(io, p->n_lval); + if (R2TEST(r)) { + fprintf(io, "(%s)", rnames[R2UPK1(r)]); + if (R2UPK3(r) == 1) + fprintf(io, "+"); + } else + fprintf(io, "(%s)", rnames[p->n_rval]); + return; + case ICON: + /* addressable value of the constant */ + conput(io, p); + return; + + case REG: + switch (p->n_type) { + case LONG: + case ULONG: + fprintf(io, "r%c", rnames[p->n_rval][1]); + break; + default: + fprintf(io, "%s", rnames[p->n_rval]); + } + return; + + case UMUL: + if (tshape(p, STARNM)) { + printf("*"); + adrput(io, p->n_left); + break; + } + /* FALLTHROUGH */ + default: + comperr("illegal address, op %d, node %p", p->n_op, p); + return; + + } +} + +static char * +ccbranches[] = { + "jeq", /* jumpe */ + "jne", /* jumpn */ + "jle", /* jumple */ + "jlt", /* jumpl */ + "jge", /* jumpge */ + "jgt", /* jumpg */ + "jlos", /* jumple (jlequ) */ + "jlo", /* jumpl (jlssu) */ + "jhis", /* jumpge (jgequ) */ + "jhi", /* jumpg (jgtru) */ +}; + + +/* printf conditional and unconditional branches */ +void +cbgen(int o, int lab) +{ + if (o < EQ || o > UGT) + comperr("bad conditional branch: %s", opst[o]); + printf("%s " LABFMT "\n", ccbranches[o-EQ], lab); +} + +#define IS1CON(p) ((p)->n_op == ICON && (p)->n_lval == 1) + +/* + * Move postfix operators to the next statement, unless they are + * within a function call or a branch. + */ +static void +cvtree(NODE *p, struct interpass *ip2) +{ + struct interpass *ip; + NODE *q; + + if (callop(p->n_op) || p->n_op == CBRANCH) + return; + + if ((p->n_op == PLUS || p->n_op == MINUS) && + IS1CON(p->n_right) && (q = p->n_left)->n_op == ASSIGN && + treecmp(q->n_left, q->n_right->n_left) && + IS1CON(q->n_right->n_right)) { + if ((p->n_op == PLUS && q->n_right->n_op == MINUS) || + (p->n_op == MINUS && q->n_right->n_op == PLUS)) { + nfree(p->n_right); + *p = *q->n_left; + if (optype(p->n_op) != LTYPE) + p->n_left = tcopy(p->n_left); + ip = ipnode(q); + DLIST_INSERT_AFTER(ip2, ip, qelem); + return; + } + } + if (optype(p->n_op) == BITYPE) + cvtree(p->n_right, ip2); + if (optype(p->n_op) != LTYPE) + cvtree(p->n_left, ip2); +} + +/* + * Convert AND to BIC. + */ +static void +fixops(NODE *p, void *arg) +{ + static int fltwritten; + + if (!fltwritten && (p->n_type == FLOAT || p->n_type == DOUBLE)) { + printf(".globl fltused\n"); + fltwritten = 1; + } + switch (p->n_op) { + case AND: + if (p->n_right->n_op == ICON) { + p->n_right->n_lval = ((~p->n_right->n_lval) & 0177777); + } else if (p->n_right->n_op == COMPL) { + NODE *q = p->n_right->n_left; + nfree(p->n_right); + p->n_right = q; + } else + p->n_right = mkunode(COMPL, p->n_right, 0, p->n_type); + break; + case RS: + p->n_right = mkunode(UMINUS, p->n_right, 0, p->n_right->n_type); + p->n_op = LS; + break; + case EQ: + case NE: /* Hack not to clear bits if FORCC */ + if (p->n_left->n_op == AND) + fixops(p->n_left, 0); /* Convert an extra time */ + break; + } +} + +void +myreader(struct interpass *ipole) +{ + struct interpass *ip; + +#ifdef PCC_DEBUG + if (x2debug) { + printf("myreader before\n"); + printip(ipole); + } +#endif + DLIST_FOREACH(ip, ipole, qelem) { + if (ip->type != IP_NODE) + continue; + walkf(ip->ip_node, fixops, 0); + canon(ip->ip_node); /* call it early */ + } +#ifdef PCC_DEBUG + if (x2debug) { + printf("myreader middle\n"); + printip(ipole); + } +#endif + DLIST_FOREACH(ip, ipole, qelem) { + if (ip->type == IP_NODE) + cvtree(ip->ip_node, ip); + } +#ifdef PCC_DEBUG + if (x2debug) { + printf("myreader after\n"); + printip(ipole); + } +#endif +} + +/* + * Remove SCONVs where the left node is an OREG with a smaller type. + */ +static void +delsconv(NODE *p, void *arg) +{ +#if 0 + NODE *l; + + if (p->n_op != SCONV || (l = p->n_left)->n_op != OREG) + return; + if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == LONG) { + p->n_op = OREG; + p->n_lval = l->n_lval; /* high word */ + p->n_rval = l->n_rval; + nfree(l); + } +#endif + /* Could do this for char etc. also */ +} + +void +mycanon(NODE *p) +{ + walkf(p, delsconv, 0); +} + +void +myoptim(struct interpass *ip) +{ +} + +void +rmove(int s, int d, TWORD t) +{ + if (t < LONG || t > BTMASK) { + printf("mov%s %s,%s\n", t < SHORT ? "b" : "", + rnames[s],rnames[d]); /* XXX char should be full reg? */ + } else if (t == LONG || t == ULONG) { + /* avoid trashing double regs */ + if (d > s) + printf("mov r%c,r%c\nmov r%c,r%c\n", + rnames[s][2],rnames[d][2], + rnames[s][1],rnames[d][1]); + else + printf("mov r%c,r%c\nmov r%c,r%c\n", + rnames[s][1],rnames[d][1], + rnames[s][2],rnames[d][2]); + } else if (t == FLOAT || t == DOUBLE) { + printf("movf %s,%s\n", rnames[s],rnames[d]); + } else + comperr("bad float rmove: %d %d %x", s, d, t); + +} + +/* + * For class c, find worst-case displacement of the number of + * registers in the array r[] indexed by class. + */ +int +COLORMAP(int c, int *r) +{ + switch (c) { + case CLASSA: + return (r[CLASSB] * 2 + r[CLASSA]) < 5; + case CLASSB: + if (r[CLASSB] > 1) return 0; + if (r[CLASSB] == 1 && r[CLASSA] > 0) return 0; + if (r[CLASSA] > 2) return 0; + return 1; + case CLASSC: + return r[CLASSC] < 8; + } + return 0; +} + +char *rnames[] = { + "r0", "r1", "r2", "r3", "r4", "r5", "sp", "pc", + "r01", "r12", "r23", "r34", "XXX", "XXX", "XXX", "XXX", + "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "XXX", "XXX", +}; + +/* + * Return a class suitable for a specific type. + */ +int +gclass(TWORD t) +{ + if (t < LONG || t > BTMASK) + return CLASSA; + if (t == LONG || t == ULONG) + return CLASSB; + if (t == FLOAT || t == DOUBLE || t == LDOUBLE) + return CLASSC; + comperr("gclass"); + return CLASSD; +} + +static int +argsiz(NODE *p) +{ + TWORD t = p->n_type; + + if (t == LONG || t == ULONG || t == FLOAT) + return 4; + if (t == DOUBLE) + return 8; + if (t == STRTY || t == UNIONTY) + return p->n_stsize; + return 2; +} + +/* + * Argument specialties. + */ +void +lastcall(NODE *p) +{ + NODE *op = p; + int size = 0; + + /* + * Calculate arg sizes. + * Mark first arg not to have - before it. + */ + p->n_qual = 0; + if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL) + return; + for (p = p->n_right; p->n_op == CM; p = p->n_left) { + p->n_right->n_qual = 0; + size += argsiz(p->n_right); + } + p->n_qual = 0; + size += argsiz(p); + p = op->n_right; + + if (p->n_op == CM) + p = p->n_right; + if (p->n_type == FLOAT || p->n_type == DOUBLE || + p->n_type == STRTY || p->n_type == UNIONTY) + op->n_flags |= NLOCAL1; /* Does not use stack slot */ + else + op->n_flags &= ~NLOCAL1; + op->n_qual = size; /* XXX */ +} + +static int +is1con(NODE *p) +{ + if (p->n_op == ICON && p->n_lval == 1) + return 1; + return 0; +} + +/* + * Special shapes. + */ +int +special(NODE *p, int shape) +{ + CONSZ s; + + switch (shape) { + case SANDSCON: + s = ~p->n_lval; + if (s < 65536 || s > -65537) + return SRDIR; + break; + case SINCB: /* Check if subject for post-inc */ + if (p->n_op == ASSIGN && p->n_right->n_op == PLUS && + treecmp(p->n_left, p->n_right->n_left) && + is1con(p->n_right->n_right)) + return SRDIR; + break; + case SARGSUB: + if (p->n_op == MINUS && p->n_right->n_op == ICON && + p->n_left->n_op == REG) + return SRDIR; + break; + case SARGINC: + if (p->n_op == MINUS && is1con(p->n_right)) + return special(p->n_left, SINCB); + break; + } + return SRNOPE; +} + +/* + * Target-dependent command-line options. + */ +void +mflags(char *str) +{ +} + +/* + * Do something target-dependent for xasm arguments. + */ +int +myxasm(struct interpass *ip, NODE *p) +{ + return 0; +} + +int +fldexpand(NODE *p, int cookie, char **cp) +{ + return 0; +} + diff --git a/compilers/pcc/pcc-1.0.0/arch/pdp11/macdefs.h b/compilers/pcc/pcc-1.0.0/arch/pdp11/macdefs.h new file mode 100644 index 00000000..e7b5754d --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/pdp11/macdefs.h @@ -0,0 +1,237 @@ +/* $Id: macdefs.h,v 1.4 2009/01/24 21:43:49 gmcgarry Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Machine-dependent defines for both passes. + */ + +/* + * Convert (multi-)character constant to integer. + */ +#define makecc(val,i) lastcon = i ? (val<<8)|lastcon : val + +#define ARGINIT 32 /* # bits above r5 where arguments start */ +#define AUTOINIT 64 /* # bits below r5 where automatics start */ + +/* + * Storage space requirements + */ +#define SZCHAR 8 +#define SZBOOL 8 +#define SZINT 16 +#define SZFLOAT 32 +#define SZDOUBLE 64 +#define SZLDOUBLE 64 +#define SZLONG 32 +#define SZSHORT 16 +#define SZLONGLONG 64 +#define SZPOINT(t) 16 + +/* + * Alignment constraints + */ +#define ALCHAR 8 +#define ALBOOL 8 +#define ALINT 16 +#define ALFLOAT 16 +#define ALDOUBLE 16 +#define ALLDOUBLE 16 +#define ALLONG 16 +#define ALLONGLONG 16 +#define ALSHORT 16 +#define ALPOINT 16 +#define ALSTRUCT 16 +#define ALSTACK 16 + +/* + * Min/max values. + */ +#define MIN_CHAR -128 +#define MAX_CHAR 127 +#define MAX_UCHAR 255 +#define MIN_SHORT -32768 +#define MAX_SHORT 32767 +#define MAX_USHORT 65535 +#define MIN_INT (-0x7fff-1) +#define MAX_INT 0x7fff +#define MAX_UNSIGNED 0xffff +#define MIN_LONG (-0x7fffffff-1) +#define MAX_LONG 0x7fffffff +#define MAX_ULONG 0xffffffff +#define MIN_LONGLONG 0x8000000000000000LL +#define MAX_LONGLONG 0x7fffffffffffffffLL +#define MAX_ULONGLONG 0xffffffffffffffffULL + +/* Default char is signed */ +#undef CHAR_UNSIGNED +#define BOOL_TYPE CHAR /* what used to store _Bool */ + +/* + * Use large-enough types. + */ +typedef long long CONSZ; +typedef unsigned long long U_CONSZ; +typedef long long OFFSZ; + +#define CONFMT "%lld" /* format for printing constants */ +#define LABFMT "L%d" /* format for printing labels */ +#ifdef LANG_F77 +#define BLANKCOMMON "_BLNK_" +#define MSKIREG (M(TYSHORT)|M(TYLONG)) +#define TYIREG TYLONG +#define FSZLENG FSZLONG +#define AUTOREG EBP +#define ARGREG EBP +#define ARGOFFSET 8 +#endif + +#define BACKAUTO /* stack grows negatively for automatics */ +#define BACKTEMP /* stack grows negatively for temporaries */ + +#undef FIELDOPS /* no bit-field instructions */ +#define RTOLBYTES /* bytes are numbered right to left */ + +#define ENUMSIZE(high,low) INT /* enums are always stored in full int */ + +/* Definitions mostly used in pass2 */ + +#define BYTEOFF(x) ((x)&01) +#define wdal(k) (BYTEOFF(k)==0) +#define BITOOR(x) (x) /* bit offset to oreg offset XXX die! */ + +#define STOARG(p) +#define STOFARG(p) +#define STOSTARG(p) +#define genfcall(a,b) gencall(a,b) + +#define FINDMOPS /* pdp11 has instructions that modifies memory */ + +#define szty(t) ((t) == DOUBLE || (t) == LONGLONG || (t) == ULONGLONG ? 4 : \ + (t) == FLOAT || (t) == LONG || (t) == ULONG ? 2 : 1) + +/* + * The pdp11 has 3 register classes, 16-bit, 32-bit and floats. + * Class membership and overlaps are defined in the macros RSTATUS + * and ROVERLAP below. + * + * The classes used on pdp11 are: + * A - 16-bit + * B - 32-bit (concatenated 16-bit) + * C - floating point + */ +#define R0 000 /* Scratch and return register */ +#define R1 001 /* Scratch and secondary return register */ +#define R2 002 /* Scratch register */ +#define R3 003 /* Scratch register */ +#define R4 004 /* Scratch register */ +#define R5 005 /* Frame pointer */ +#define SP 006 /* Stack pointer */ +#define PC 007 /* Program counter */ + +#define R01 010 +#define R12 011 +#define R23 012 +#define R34 013 + +#define FR0 020 +#define FR1 021 +#define FR2 022 +#define FR3 023 +#define FR4 024 +#define FR5 025 +#define FR6 026 +#define FR7 027 + +#define MAXREGS 030 /* 24 registers */ + +#define RSTATUS \ + SAREG|TEMPREG, SAREG|TEMPREG, SAREG, SAREG, SAREG, 0, 0, 0, \ + SBREG, SBREG, SBREG, SBREG, 0, 0, 0, 0, \ + SCREG, SCREG, SCREG, SCREG, 0, 0, 0, 0 + +#define ROVERLAP \ + /* 8 basic registers */\ + { R01, -1 }, \ + { R01, R12, -1 }, \ + { R12, R23, -1 }, \ + { R23, R34, -1 }, \ + { R34, -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ +\ + /* 4 long registers */\ + { R0, R1, R12, -1 }, \ + { R1, R2, R01, R23, -1 }, \ + { R2, R3, R12, R34, -1 }, \ + { R3, R4, R23, -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ +\ + /* The fp registers do not overlap with anything */\ + { -1 },\ + { -1 },\ + { -1 },\ + { -1 },\ + { -1 },\ + { -1 },\ + { -1 },\ + { -1 }, + + +/* Return a register class based on the type of the node */ + +#define PCLASS(p) (p->n_type < LONG || p->n_type > BTMASK ? SAREG : \ + (p->n_type == LONG || p->n_type == ULONG ? SBREG : SCREG)) + +#define NUMCLASS 3 /* highest number of reg classes used */ + +int COLORMAP(int c, int *r); +#define GCLASS(x) (x < 8 ? CLASSA : x < 16 ? CLASSB : CLASSC) +#define DECRA(x,y) (((x) >> (y*5)) & 31) /* decode encoded regs */ +#define ENCRD(x) (x) /* Encode dest reg in n_reg */ +#define ENCRA1(x) ((x) << 5) /* A1 */ +#define ENCRA2(x) ((x) << 10) /* A2 */ +#define ENCRA(x,y) ((x) << (5+y*5)) /* encode regs in int */ +#define RETREG(x) ((x) == LONG || (x) == ULONG ? R01 : \ + (x) == FLOAT || (x) == DOUBLE ? FR0 : R0) + +//#define R2REGS 1 /* permit double indexing */ + +/* XXX - to die */ +#define FPREG R5 /* frame pointer */ +#define STKREG SP /* stack pointer */ + +/* A bunch of specials to make life easier for pdp11 */ +#define SANDSCON (MAXSPECIAL+1) +#define SINCB (MAXSPECIAL+2) /* post-increment */ +#define SINCW (MAXSPECIAL+3) /* post-increment */ +#define SARGSUB (MAXSPECIAL+4) /* arg pointer to array */ +#define SARGINC (MAXSPECIAL+5) /* post-increment arg */ diff --git a/compilers/pcc/pcc-1.0.0/arch/pdp11/order.c b/compilers/pcc/pcc-1.0.0/arch/pdp11/order.c new file mode 100644 index 00000000..15d1588b --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/pdp11/order.c @@ -0,0 +1,249 @@ +/* $Id: order.c,v 1.3 2008/10/04 08:43:17 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass2.h" + +#include + +int canaddr(NODE *); + +/* is it legal to make an OREG or NAME entry which has an + * offset of off, (from a register of r), if the + * resulting thing had type t */ +int +notoff(TWORD t, int r, CONSZ off, char *cp) +{ + return(0); /* YES */ +} + +static int +inctree(NODE *p) +{ + if (p->n_op == MINUS && p->n_left->n_op == ASSIGN && + p->n_left->n_right->n_op == PLUS && + treecmp(p->n_left->n_left, p->n_left->n_right->n_left) && + p->n_right->n_op == ICON && p->n_right->n_lval == 1 && + p->n_left->n_right->n_right->n_op == ICON && + p->n_left->n_right->n_right->n_lval == 1) { + /* post-increment by 1; (r0)+ */ + if (isreg(p->n_left->n_left)) /* Ignore if index not in reg */ + return 1; + } + return 0; +} + +/* + * Turn a UMUL-referenced node into OREG. + * Be careful about register classes, this is a place where classes change. + */ +void +offstar(NODE *p, int shape) +{ + if (x2debug) + printf("offstar(%p)\n", p); + + if (isreg(p)) + return; /* Is already OREG */ + + if (p->n_op == UMUL) + p = p->n_left; /* double indexed umul */ + + if (inctree(p)) /* Do post-inc conversion */ + return; + + if( p->n_op == PLUS || p->n_op == MINUS ){ + if (p->n_right->n_op == ICON) { + if (isreg(p->n_left) == 0) + (void)geninsn(p->n_left, INAREG); + /* Converted in ormake() */ + return; + } + } + (void)geninsn(p, INAREG); +} + +/* + * Do the actual conversion of offstar-found OREGs into real OREGs. + */ +void +myormake(NODE *p) +{ + NODE *q = p->n_left; + + if (x2debug) { + printf("myormake(%p)\n", p); + fwalk(p, e2print, 0); + } + if (inctree(q)) { + if (q->n_left->n_left->n_op == TEMP) + return; + p->n_op = OREG; + p->n_lval = 0; /* Add support for index offset */ + p->n_rval = R2PACK(regno(q->n_left->n_left), 0, 1); + tfree(q); + return; + } + if (q->n_op != OREG) + return; + p->n_op = OREG; + p->n_lval = q->n_lval; + p->n_rval = R2PACK(q->n_rval, 0, 0); + nfree(q); +} + +/* + * Shape matches for UMUL. Cooperates with offstar(). + */ +int +shumul(NODE *p, int shape) +{ + + if (x2debug) + printf("shumul(%p)\n", p); + + if (p->n_op == NAME && (shape & STARNM)) + return SRDIR; + if (shape & SOREG) + return SROREG; /* Calls offstar */ + return SRNOPE; +} + +/* + * Rewrite operations on binary operators (like +, -, etc...). + * Called as a result of table lookup. + */ +int +setbin(NODE *p) +{ + + if (x2debug) + printf("setbin(%p)\n", p); + return 0; + +} + +/* setup for assignment operator */ +int +setasg(NODE *p, int cookie) +{ + if (x2debug) + printf("setasg(%p)\n", p); + return(0); +} + +/* setup for unary operator */ +int +setuni(NODE *p, int cookie) +{ + return(0); +} + +/* + * Special handling of some instruction register allocation. + */ +struct rspecial * +nspecial(struct optab *q) +{ + switch (q->op) { + case MUL: + if (q->visit == INAREG) { + static struct rspecial s[] = { { NLEFT, R1 }, { 0 } }; + return s; + } else if (q->visit == INBREG) { + static struct rspecial s[] = { { NRES, R01 }, { 0 } }; + return s; + } + break; + + case DIV: + if (q->visit == INAREG && q->ltype == TUNSIGNED) { + static struct rspecial s[] = { + { NLEFT, R0 }, { NRIGHT, R1 }, { NRES, R0 }, { 0 } }; + return s; + } else if (q->visit == INAREG) { + static struct rspecial s[] = { + { NRES, R0 }, { 0 } }; + return s; + } else if (q->visit == INBREG) { + static struct rspecial s[] = { { NRES, R01 }, { 0 } }; + return s; + } + break; + + case MOD: + if (q->visit == INAREG && q->ltype == TUNSIGNED) { + static struct rspecial s[] = { + { NLEFT, R0 }, { NRIGHT, R1 }, { NRES, R0 }, { 0 } }; + return s; + } else if (q->visit == INBREG) { + static struct rspecial s[] = { { NRES, R01 }, { 0 } }; + return s; + } + break; + + case SCONV: + if (q->lshape == SAREG) { + static struct rspecial s[] = { + { NLEFT, R1 }, { NRES, R01 }, { 0 } }; + return s; + } + break; + } + comperr("nspecial entry %d", q - table); + return 0; /* XXX gcc */ +} + +/* + * Set evaluation order of a binary node if it differs from default. + */ +int +setorder(NODE *p) +{ + return 0; /* nothing differs on x86 */ +} + +/* + * set registers in calling conventions live. + */ +int * +livecall(NODE *p) +{ + static int r[] = { -1 }; + + return r; +} + +/* + * Signal whether the instruction is acceptable for this target. + */ +int +acceptable(struct optab *op) +{ + return 1; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/pdp11/table.c b/compilers/pcc/pcc-1.0.0/arch/pdp11/table.c new file mode 100644 index 00000000..586b039f --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/pdp11/table.c @@ -0,0 +1,843 @@ +/* $Id: table.c,v 1.5 2008/10/19 15:25:25 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +# include "pass2.h" + +# define TLL TLONGLONG|TULONGLONG +# define ANYSIGNED TINT|TLONG|TSHORT|TCHAR +# define ANYUSIGNED TUNSIGNED|TULONG|TUSHORT|TUCHAR +# define ANYFIXED ANYSIGNED|ANYUSIGNED +# define TUWORD TUNSIGNED +# define TSWORD TINT +# define TWORD TUWORD|TSWORD +# define ANYSH SCON|SAREG|SOREG|SNAME +# define ARONS SAREG|SOREG|SNAME|STARNM + +struct optab table[] = { +/* First entry must be an empty entry */ +{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", }, + +/* PCONVs are usually not necessary */ +{ PCONV, INAREG, + SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + 0, RLEFT, + "", }, + +/* convert char to int or unsigned */ +{ SCONV, INAREG, + SAREG, TCHAR, + SAREG, TINT|TUNSIGNED, + NAREG|NASL, RESC1, + "", }, /* chars are stored as ints in registers */ + +{ SCONV, INAREG, + SOREG|SCON|SNAME, TCHAR, + SAREG, TINT, + NAREG|NASL, RESC1, + "movb AL,A1\n", }, + +/* convert uchar to int or unsigned */ +{ SCONV, INAREG, + SAREG|SOREG|SCON|SNAME, TUCHAR, + SAREG, TINT|TUNSIGNED, + NAREG, RESC1, + "clr A1\nbisb AL,A1\n", }, + +/* convert (u)int to (u)char. Nothing to do. */ +{ SCONV, INAREG, + SAREG, TWORD, + SANY, TCHAR|TUCHAR, + 0, RLEFT, + "", }, + +/* convert (u)int to (u)int */ +{ SCONV, INAREG, + SAREG, TWORD, + SANY, TWORD, + 0, RLEFT, + "", }, + +/* convert pointer to (u)int */ +{ SCONV, INAREG, + SAREG, TPOINT, + SANY, TWORD, + 0, RLEFT, + "", }, + +/* convert int to long from memory */ +{ SCONV, INBREG, + SNAME|SOREG, TINT, + SANY, TLONG, + NBREG, RESC1, + "mov AL,U1\nsxt A1\n", }, + +/* int -> (u)long. XXX - only in r0 and r1 */ +{ SCONV, INBREG, + SAREG, TINT, + SANY, TLONG|TULONG, + NSPECIAL|NBREG|NBSL, RESC1, + "tst AL\nsxt r0\n", }, + +/* unsigned -> (u)long. XXX - only in r0 and r1 */ +{ SCONV, INBREG, + SAREG, TUNSIGNED, + SANY, TLONG|TULONG, + NSPECIAL|NBREG|NBSL, RESC1, + "clr r0\n", }, + +/* uint -> double */ +{ SCONV, INCREG, + SAREG|SNAME|SOREG|SCON, TUNSIGNED, + SANY, TFLOAT|TDOUBLE, + NCREG|NCSL, RESC1, + "mov AL,-(sp)\nclr -(sp)\n" + "setl\nmovif (sp)+,A1\nseti\n", }, + +/* long -> int */ +{ SCONV, INAREG, + SBREG|SOREG|SNAME, TLONG|TULONG, + SAREG, TWORD, + NAREG|NASL, RESC1, + "mov UL,A1\n", }, + + +/* (u)long -> (u)long, nothing */ +{ SCONV, INBREG, + SBREG, TLONG|TULONG, + SANY, TLONG|TULONG, + NBREG|NBSL, RESC1, + "", }, + +/* long -> double */ +{ SCONV, INCREG, + SBREG|SNAME|SOREG|SCON, TLONG, + SANY, TFLOAT|TDOUBLE, + NCREG|NCSL, RESC1, + "mov UL,-(sp)\nmov AL,-(sp)\n" + "setl\nmovif (sp)+,A1\nseti\n", }, + +/* + * Subroutine calls. + */ +{ CALL, INBREG, + SCON, TANY, + SBREG, TLONG|TULONG, + NBREG|NBSL, RESC1, + "jsr pc,*CL\nZC", }, + +{ UCALL, INBREG, + SCON, TANY, + SBREG, TLONG|TULONG, + NBREG|NBSL, RESC1, + "jsr pc,*CL\n", }, + +{ CALL, FOREFF, + SCON|SNAME|SOREG, TANY, + SANY, TANY, + 0, 0, + "jsr pc,*AL\nZC", }, + +{ UCALL, FOREFF, + SCON|SNAME|SOREG, TANY, + SANY, TANY, + 0, 0, + "jsr pc,*AL\n", }, + +{ CALL, INAREG, + SCON|SOREG|SNAME, TANY, + SAREG, TWORD|TPOINT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + "jsr pc,*AL\nZC", }, + +{ UCALL, INAREG, + SCON|SOREG|SNAME, TANY, + SAREG, TWORD|TPOINT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + "jsr pc,*AL\n", }, + +{ CALL, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, 0, + "jsr pc,(AL)\nZC", }, + +{ UCALL, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, 0, + "jsr pc,(AL)\n", }, + +{ CALL, INAREG, + SAREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + "jsr pc,(AL)\nZC", }, + +{ UCALL, INAREG, + SAREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + "jsr pc,(AL)\n", }, + +/* + * The next rules handle all binop-style operators. + */ +/* Add one to anything left but use only for side effects */ +{ PLUS, FOREFF|INAREG|FORCC, + SAREG|SNAME|SOREG, TWORD|TPOINT, + SONE, TANY, + 0, RLEFT|RESCC, + "inc AL\n", }, + +/* add one for char to reg, special handling */ +{ PLUS, FOREFF|INAREG|FORCC, + SAREG, TCHAR|TUCHAR, + SONE, TANY, + 0, RLEFT|RESCC, + "inc AL\n", }, + +/* add one for char to memory */ +{ PLUS, FOREFF|FORCC, + SNAME|SOREG|STARNM, TCHAR|TUCHAR, + SONE, TANY, + 0, RLEFT|RESCC, + "incb AL\n", }, + +{ PLUS, INBREG|FOREFF, + SBREG, TLONG, + SBREG|SNAME|SOREG|SCON, TLONG, + 0, RLEFT, + "add AR,AL\nadd UR,UL\nadc AL\n", }, + +/* Add to reg left and reclaim reg */ +{ PLUS, INAREG|FOREFF|FORCC, + SAREG|SNAME|SOREG, TWORD|TPOINT, + SAREG|SNAME|SOREG|SCON, TWORD|TPOINT, + 0, RLEFT|RESCC, + "add AR,AL\n", }, + +/* Add to anything left but use only for side effects */ +{ PLUS, FOREFF|FORCC, + SNAME|SOREG, TWORD|TPOINT, + SAREG|SNAME|SOREG|SCON, TWORD|TPOINT, + 0, RLEFT|RESCC, + "add AR,AL\n", }, + +{ PLUS, INAREG|FOREFF|FORCC, + SAREG, TCHAR|TUCHAR, + SAREG|SNAME|SOREG|SCON, TCHAR|TUCHAR, + 0, RLEFT|RESCC, + "add AR,AL\n", }, + +/* Post-increment read, byte */ +{ MINUS, INAREG, + SINCB, TCHAR|TUCHAR, + SONE, TANY, + NAREG, RESC1, + "movb ZG,A1\nincb ZG\n", }, + +/* Post-increment read, int */ +{ MINUS, INAREG, + SINCB, TWORD|TPOINT, + SONE, TANY, + NAREG, RESC1, + "mov ZG,A1\ninc ZG\n", }, + +{ MINUS, INBREG|FOREFF, + SBREG, TLONG|TULONG, + SBREG|SNAME|SOREG|SCON, TLONG|TULONG, + 0, RLEFT, + "sub AR,AL\nsub UR,UL\nsbc AL\n", }, + +/* Sub one from anything left */ +{ MINUS, FOREFF|INAREG|FORCC, + SAREG|SNAME|SOREG, TWORD|TPOINT, + SONE, TANY, + 0, RLEFT|RESCC, + "dec AL\n", }, + +{ MINUS, INAREG|FOREFF, + SAREG, TWORD|TPOINT, + SAREG|SNAME|SOREG|SCON, TWORD|TPOINT, + 0, RLEFT, + "sub AR,AL\n", }, + +/* Sub from anything left but use only for side effects */ +{ MINUS, FOREFF|INAREG|FORCC, + SAREG|SNAME|SOREG, TWORD|TPOINT, + SAREG|SNAME|SOREG|SCON, TWORD|TPOINT, + 0, RLEFT|RESCC, + "sub AR,AL\n", }, + +/* Sub one left but use only for side effects */ +{ MINUS, FOREFF|FORCC, + SAREG|SNAME|SOREG, TCHAR|TUCHAR, + SONE, TANY, + 0, RLEFT|RESCC, + "decb AL\n", }, + +/* Sub from anything left but use only for side effects */ +{ MINUS, FOREFF|FORCC, + SAREG|SNAME|SOREG, TCHAR|TUCHAR, + SAREG|SNAME|SOREG|SCON, TCHAR|TUCHAR|TWORD|TPOINT, + 0, RLEFT|RESCC, + "subb AR,AL\n", }, + +/* + * The next rules handle all shift operators. + */ +{ LS, INBREG|FOREFF, + SBREG, TLONG|TULONG, + SANY, TANY, + 0, RLEFT, + "ashc AR,AL\n", }, + +{ LS, INAREG|FOREFF, + SAREG, TWORD, + SONE, TANY, + 0, RLEFT, + "asl AL\n", }, + +{ LS, INAREG|FOREFF, + SAREG, TWORD, + ANYSH, TWORD, + 0, RLEFT, + "ash AR,AL\n", }, + +/* + * The next rules takes care of assignments. "=". + */ + +/* First optimizations, in lack of weight it uses first found */ +/* Start with class A registers */ + +/* Clear word at address */ +{ ASSIGN, FOREFF|FORCC, + ARONS, TWORD|TPOINT, + SZERO, TANY, + 0, RESCC, + "clr AL\n", }, + +/* Clear word at reg */ +{ ASSIGN, FOREFF|INAREG, + SAREG, TWORD|TPOINT, + SZERO, TANY, + 0, RDEST, + "clr AL\n", }, + +/* Clear byte at address. No reg here. */ +{ ASSIGN, FOREFF, + SNAME|SOREG|STARNM, TCHAR|TUCHAR, + SZERO, TANY, + 0, RDEST, + "clrb AL\n", }, + +/* Clear byte in reg. must clear the whole register. */ +{ ASSIGN, FOREFF|INAREG, + SAREG, TCHAR|TUCHAR, + SZERO, TANY, + 0, RDEST, + "clr AL\n", }, + +/* The next is class B regs */ + +/* Clear long at address or in reg */ +{ ASSIGN, FOREFF|INBREG, + SNAME|SOREG|SBREG, TLONG|TULONG, + SZERO, TANY, + 0, RDEST, + "clr AL\nclr UL\n", }, + +/* Save 2 bytes if high-order bits are zero */ +{ ASSIGN, FOREFF|INBREG, + SBREG, TLONG|TULONG, + SSCON, TLONG, + 0, RDEST, + "mov UR,UL\nsxt AL\n", }, + +/* Must have multiple rules for long otherwise regs may be trashed */ +{ ASSIGN, FOREFF|INBREG, + SBREG, TLONG|TULONG, + SCON|SNAME|SOREG, TLONG|TULONG, + 0, RDEST, + "mov AR,AL\nmov UR,UL\n", }, + +{ ASSIGN, FOREFF|INBREG, + SNAME|SOREG, TLONG|TULONG, + SBREG, TLONG|TULONG, + 0, RDEST, + "mov AR,AL\nmov UR,UL\n", }, + +{ ASSIGN, FOREFF, + SNAME|SOREG, TLONG|TULONG, + SCON|SNAME|SOREG, TLONG|TULONG, + 0, 0, + "mov AR,AL\nmov UR,UL\n", }, + +{ ASSIGN, INBREG|FOREFF, + SBREG, TLONG|TULONG, + SBREG, TLONG|TULONG, + 0, RDEST, + "ZE\n", }, + +{ ASSIGN, FOREFF|INAREG|FORCC, + SAREG, TWORD|TPOINT, + SAREG|SNAME|SOREG|SCON, TWORD|TPOINT, + 0, RDEST|RESCC, + "mov AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG|FORCC, + ARONS, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + 0, RDEST|RESCC, + "mov AR,AL\n", }, + +{ ASSIGN, FOREFF|FORCC, + SNAME|SOREG, TWORD|TPOINT, + SNAME|SOREG|SCON, TWORD|TPOINT, + 0, RESCC, + "mov AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG|FORCC, + SAREG, TCHAR|TUCHAR, + ARONS|SCON, TCHAR|TUCHAR, + 0, RDEST|RESCC, + "movb AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG|FORCC, + ARONS, TCHAR|TUCHAR, + SAREG, TCHAR|TUCHAR, + 0, RDEST|RESCC, + "movb AR,AL\n", }, + +{ ASSIGN, FOREFF|FORCC, + SNAME|SOREG|STARNM, TCHAR|TUCHAR, + SNAME|SOREG|SCON|STARNM, TCHAR|TUCHAR, + 0, RDEST|RESCC, + "movb AR,AL\n", }, + +{ ASSIGN, FOREFF|INCREG, + SCREG, TDOUBLE, + SNAME|SOREG|SCON, TDOUBLE, + 0, RDEST, + "movf AR,AL\n", }, + +{ ASSIGN, FOREFF|INCREG, + SCREG, TFLOAT, + SNAME|SOREG|SCON, TFLOAT, + 0, RDEST, + "movof AR,AL\n", }, + +{ ASSIGN, FOREFF|INCREG, + SNAME|SOREG|SCREG, TDOUBLE, + SCREG, TDOUBLE, + 0, RDEST, + "movf AR,AL\n", }, + +{ ASSIGN, FOREFF|INCREG, + SNAME|SOREG|SCREG, TFLOAT, + SCREG, TFLOAT, + 0, RDEST, + "movfo AR,AL\n", }, + +/* + * DIV/MOD/MUL + */ +/* XXX - mul may use any odd register, only r1 for now */ +{ MUL, INAREG, + SAREG, TWORD|TPOINT, + SAREG|SNAME|SOREG|SCON, TWORD|TPOINT, + NSPECIAL, RLEFT, + "mul AR,AL\n", }, + +{ MUL, INBREG, + SBREG|SNAME|SCON|SOREG, TLONG|TULONG, + SBREG|SNAME|SCON|SOREG, TLONG|TULONG, + NSPECIAL|NBREG|NBSL|NBSR, RESC1, + "mov UR,-(sp)\nmov AR,-(sp)\n" + "mov UL,-(sp)\nmov AL,-(sp)\n" + "jsr pc,lmul\nadd $10,sp\n", }, + +{ MUL, INCREG, + SCREG, TFLOAT|TDOUBLE, + SCREG|SNAME|SOREG, TFLOAT|TDOUBLE, + 0, RLEFT, + "mulf AR,AL\n", }, + +/* need extra move to be sure N flag is correct for sxt */ +{ DIV, INAREG, + ANYSH, TINT|TPOINT, + ANYSH, TINT|TPOINT, + NSPECIAL, RDEST, + "mov AL,r1\nsxt r0\ndiv AR,r0\n", }, + +/* udiv uses args in registers */ +{ DIV, INAREG, + SAREG, TUNSIGNED, + SAREG, TUNSIGNED, + NSPECIAL|NAREG|NASL|NASR, RESC1, + "jsr pc,udiv\n", }, + +{ DIV, INBREG, + SBREG|SNAME|SCON|SOREG, TLONG|TULONG, + SBREG|SNAME|SCON|SOREG, TLONG|TULONG, + NSPECIAL|NBREG|NBSL|NBSR, RESC1, + "mov UR,-(sp)\nmov AR,-(sp)\n" + "mov UL,-(sp)\nmov AL,-(sp)\n" + "jsr pc,ldiv\nadd $10,sp\n", }, + +{ DIV, INCREG, + SCREG, TFLOAT|TDOUBLE, + SCREG|SNAME|SOREG, TFLOAT|TDOUBLE, + 0, RLEFT, + "divf AR,AL\n", }, + +/* XXX merge the two below to one */ +{ MOD, INBREG, + SBREG|SNAME|SCON|SOREG, TLONG, + SBREG|SNAME|SCON|SOREG, TLONG, + NSPECIAL|NBREG|NBSL|NBSR, RESC1, + "mov UR,-(sp)\nmov AR,-(sp)\n" + "mov UL,-(sp)\nmov AL,-(sp)\n" + "jsr pc,lrem\nadd $10,sp\n", }, + +{ MOD, INBREG, + SBREG|SNAME|SCON|SOREG, TULONG, + SBREG|SNAME|SCON|SOREG, TULONG, + NSPECIAL|NBREG|NBSL|NBSR, RESC1, + "mov UR,-(sp)\nmov AR,-(sp)\n" + "mov UL,-(sp)\nmov AL,-(sp)\n" + "jsr pc,ulrem\nadd $10,sp\n", }, + +/* urem uses args in registers */ +{ MOD, INAREG, + SAREG, TUNSIGNED, + SAREG, TUNSIGNED, + NSPECIAL|NAREG|NASL|NASR, RESC1, + "jsr pc,urem\n", }, + +/* + * Indirection operators. + */ +{ UMUL, INBREG, + SANY, TPOINT|TWORD, + SOREG, TLONG|TULONG, + NBREG, RESC1, /* |NBSL - may overwrite index reg */ + "mov AR,A1\nmov UR,U1\n", }, + +{ UMUL, INAREG, + SANY, TPOINT|TWORD, + SOREG, TPOINT|TWORD, + NAREG|NASL, RESC1, + "mov AR,A1\n", }, + +{ UMUL, INAREG, + SANY, TANY, + SOREG, TCHAR|TUCHAR, + NAREG|NASL, RESC1, + "movb AR,A1\n", }, + +/* + * Logical/branching operators + */ +{ OPLOG, FORCC, + SAREG|SOREG|SNAME|SCON, TWORD|TPOINT, + SZERO, TANY, + 0, RESCC, + "tst AL\n", }, + +{ OPLOG, FORCC, + SAREG|SOREG|SNAME|SCON, TCHAR|TUCHAR, + SZERO, TANY, + 0, RESCC, + "tstb AL\n", }, + +{ OPLOG, FORCC, + SAREG|SOREG|SNAME|SCON, TWORD|TPOINT, + SAREG|SOREG|SNAME|SCON, TWORD|TPOINT, + 0, RESCC, + "cmp AL,AR\n", }, + +{ OPLOG, FORCC, + SAREG|SOREG|SNAME|SCON, TCHAR|TUCHAR, + SAREG|SOREG|SNAME|SCON, TCHAR|TUCHAR, + 0, RESCC, + "cmpb AL,AR\n", }, + +{ OPLOG, FORCC, + SBREG|SOREG|SNAME|SCON, TLONG|TULONG, + SZERO, TANY, + 0, RNULL, + "ZD", }, + +{ OPLOG, FORCC, + SBREG|SOREG|SNAME, TLONG|TULONG, + SBREG|SOREG|SNAME, TLONG|TULONG, + 0, RNULL, + "ZF", }, + +/* AND/OR/ER/NOT */ +/* Optimize if high order bits are zero */ +{ AND, FOREFF|INBREG|FORCC, + SOREG|SNAME|SBREG, TLONG|TULONG, + SANDSCON, TLONG|TULONG, + 0, RLEFT|RESCC, + "clr AL\nbic UR,UL\n", }, + +{ AND, INBREG|FORCC, + SBREG, TLONG|TULONG, + SCON|SBREG|SOREG|SNAME, TLONG|TULONG, + 0, RLEFT|RESCC, + "bic AR,AL\nbic UR,UL\n", }, + +/* set status bits */ +{ AND, FORCC, + ARONS|SCON, TWORD|TPOINT, + ARONS|SCON, TWORD|TPOINT, + 0, RESCC, + "bit AR,AL\n", }, + +/* AND with int */ +{ AND, INAREG|FORCC|FOREFF, + SAREG|SNAME|SOREG, TWORD, + SCON|SAREG|SOREG|SNAME, TWORD, + 0, RLEFT|RESCC, + "bic AR,AL\n", }, + +/* AND with char */ +{ AND, INAREG|FORCC, + SAREG|SOREG|SNAME, TCHAR|TUCHAR, + ARONS|SCON, TCHAR|TUCHAR, + 0, RLEFT|RESCC, + "bicb AR,AL\n", }, + +{ OR, INBREG|FORCC, + SBREG, TLONG|TULONG, + SCON|SBREG|SOREG|SNAME, TLONG|TULONG, + 0, RLEFT|RESCC, + "bis AR,AL\nbis UR,UL\n", }, + +/* OR with int */ +{ OR, FOREFF|INAREG|FORCC, + ARONS, TWORD, + ARONS|SCON, TWORD, + 0, RLEFT|RESCC, + "bis AR,AL\n", }, + +/* OR with char */ +{ OR, INAREG|FORCC, + SAREG|SOREG|SNAME, TCHAR|TUCHAR, + ARONS|SCON, TCHAR|TUCHAR, + 0, RLEFT|RESCC, + "bisb AR,AL\n", }, + +/* XOR with int (extended insn) */ +{ ER, INAREG|FORCC, + ARONS, TWORD, + SAREG, TWORD, + 0, RLEFT|RESCC, + "xor AR,AL\n", }, + +/* XOR with char (extended insn) */ +{ ER, INAREG|FORCC, + SAREG, TCHAR|TUCHAR, + SAREG, TCHAR|TUCHAR, + 0, RLEFT|RESCC, + "xor AR,AL\n", }, + +/* + * Jumps. + */ +{ GOTO, FOREFF, + SCON, TANY, + SANY, TANY, + 0, RNOP, + "jbr LL\n", }, + +/* + * Convert LTYPE to reg. + */ +/* Two bytes less if high half of constant is zero */ +{ OPLTYPE, INBREG, + SANY, TANY, + SSCON, TLONG|TULONG, + NBREG, RESC1, + "mov UL,U1\nsxt A1\n", }, + +/* XXX - avoid OREG index register to be overwritten */ +{ OPLTYPE, INBREG, + SANY, TANY, + SCON|SBREG|SNAME|SOREG, TLONG|TULONG, + NBREG, RESC1, + "mov AL,A1\nmov UL,U1\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SAREG|SCON|SOREG|SNAME, TWORD|TPOINT, + NAREG|NASR, RESC1, + "mov AL,A1\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SAREG|SCON|SOREG|SNAME, TCHAR, + NAREG, RESC1, + "movb AR,A1\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SAREG|SCON|SOREG|SNAME, TUCHAR, + NAREG, RESC1, + "clr A1\nbisb AL,A1\n", }, + +{ OPLTYPE, INCREG, + SANY, TANY, + SCREG|SCON|SOREG|SNAME, TDOUBLE, + NCREG, RESC1, + "movf AL,A1\n", }, + +{ OPLTYPE, INCREG, + SANY, TANY, + SCREG|SCON|SOREG|SNAME, TFLOAT, + NCREG, RESC1, + "movof AL,A1\n", }, + +/* + * Negate a word. + */ +{ UMINUS, INAREG|FOREFF, + SAREG, TWORD|TPOINT|TCHAR|TUCHAR, + SANY, TANY, + 0, RLEFT, + "neg AL\n", }, + +{ UMINUS, INBREG|FOREFF, + SBREG|SOREG|SNAME, TLONG, + SANY, TANY, + 0, RLEFT, + "neg AL\nneg UL\nsbc AL\n", }, + + +{ COMPL, INBREG, + SBREG, TLONG|TULONG, + SANY, TANY, + 0, RLEFT, + "com AL\ncom UL\n", }, + +{ COMPL, INAREG, + SAREG, TWORD, + SANY, TANY, + 0, RLEFT, + "com AL\n", }, + +/* + * Arguments to functions. + */ +{ FUNARG, FOREFF, + SCON|SBREG|SNAME|SOREG, TLONG|TULONG, + SANY, TLONG|TULONG, + 0, RNULL, + "mov UL,ZA(sp)\nmov AL,-(sp)\n", }, + +{ FUNARG, FOREFF, + SZERO, TANY, + SANY, TANY, + 0, RNULL, + "clr ZA(sp)\n", }, + +{ FUNARG, FOREFF, + SARGSUB, TWORD|TPOINT, + SANY, TWORD|TPOINT, + 0, RNULL, + "ZB", }, + +{ FUNARG, FOREFF, + SARGINC, TWORD|TPOINT, + SANY, TWORD|TPOINT, + 0, RNULL, + "ZH", }, + +{ FUNARG, FOREFF, + SCON|SAREG|SNAME|SOREG, TWORD|TPOINT, + SANY, TWORD|TPOINT, + 0, RNULL, + "mov AL,ZA(sp)\n", }, + +{ FUNARG, FOREFF, + SCON, TCHAR|TUCHAR, + SANY, TANY, + 0, RNULL, + "mov AL,ZA(sp)\n", }, + +{ FUNARG, FOREFF, + SNAME|SOREG, TCHAR, + SANY, TCHAR, + NAREG, RNULL, + "movb AL,A1\nmov A1,ZA(sp)\n", }, + +{ FUNARG, FOREFF, + SNAME|SOREG, TUCHAR, + SANY, TUCHAR, + NAREG, RNULL, + "clr ZA(sp)\nbisb AL,(sp)\n", }, + +{ FUNARG, FOREFF, + SAREG, TUCHAR|TCHAR, + SANY, TUCHAR|TCHAR, + 0, RNULL, + "mov AL,ZA(sp)\n", }, + +{ FUNARG, FOREFF, + SCREG, TFLOAT|TDOUBLE, + SANY, TANY, + 0, RNULL, + "movf AL,ZA(sp)\n", }, + +# define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,"" + +{ UMUL, DF( UMUL ), }, + +{ ASSIGN, DF(ASSIGN), }, + +{ STASG, DF(STASG), }, + +{ FLD, DF(FLD), }, + +{ OPLEAF, DF(NAME), }, + +/* { INIT, DF(INIT), }, */ + +{ OPUNARY, DF(UMINUS), }, + +{ OPANY, DF(BITYPE), }, + +{ FREE, FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" }, +}; + +int tablesize = sizeof(table)/sizeof(table[0]); diff --git a/compilers/pcc/pcc-1.0.0/arch/powerpc/CVS/Entries b/compilers/pcc/pcc-1.0.0/arch/powerpc/CVS/Entries new file mode 100644 index 00000000..1cbada13 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/powerpc/CVS/Entries @@ -0,0 +1,8 @@ +/README/1.2/Thu Nov 22 16:47:02 2007//Tr-1-0-0-RELEASE +/code.c/1.23/Fri Nov 26 17:06:31 2010//Tr-1-0-0-RELEASE +/local.c/1.28/Fri Jan 21 21:47:59 2011//Tr-1-0-0-RELEASE +/local2.c/1.25/Fri Nov 26 17:06:31 2010//Tr-1-0-0-RELEASE +/macdefs.h/1.11/Fri Nov 26 17:06:31 2010//Tr-1-0-0-RELEASE +/order.c/1.8/Wed Jan 7 11:44:03 2009//Tr-1-0-0-RELEASE +/table.c/1.18/Fri Nov 26 17:06:31 2010//Tr-1-0-0-RELEASE +D diff --git a/compilers/pcc/pcc-1.0.0/arch/powerpc/CVS/Repository b/compilers/pcc/pcc-1.0.0/arch/powerpc/CVS/Repository new file mode 100644 index 00000000..51c88bb6 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/powerpc/CVS/Repository @@ -0,0 +1 @@ +pcc/arch/powerpc diff --git a/compilers/pcc/pcc-1.0.0/arch/powerpc/CVS/Root b/compilers/pcc/pcc-1.0.0/arch/powerpc/CVS/Root new file mode 100644 index 00000000..71e2ccb9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/powerpc/CVS/Root @@ -0,0 +1 @@ +/cvsroot diff --git a/compilers/pcc/pcc-1.0.0/arch/powerpc/CVS/Tag b/compilers/pcc/pcc-1.0.0/arch/powerpc/CVS/Tag new file mode 100644 index 00000000..060fac05 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/powerpc/CVS/Tag @@ -0,0 +1 @@ +Nr-1-0-0-RELEASE diff --git a/compilers/pcc/pcc-1.0.0/arch/powerpc/README b/compilers/pcc/pcc-1.0.0/arch/powerpc/README new file mode 100644 index 00000000..d3c86781 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/powerpc/README @@ -0,0 +1,48 @@ +macdefs.h ; machine-dependent definitions +code.c ; machine-dependent code for prologs, switches (pass 1) +local.c ; machine-dependent code for prologs, switches (pass 1) +local2.c ; misc routines and tables of register names (pass 2) +order.c ; machine-dependent code-generation strategy (pass 2) +table.c ; code templates (pass 2) + +On OS X, binaries are not ELF and all binaries are compiled PIC. To use pcc +on OS X while linking against the system libraries, use the -k option. + +Current issues: + +- no floating point (need mickey's patches to support >64 registers) +- mod/div on longlong not supported +- the stack frame is always 200 bytes - need to calculate size and patch + OREGs to temporaries and arguments [see discussion below] +- function arguments are always saved to the stack [need to change MI code] +- permanent registers >R13 are not saved [need to change MI code] +- structure arguments don't work +- return of structure doesn't work +- function pointers don't work for PIC +- constant structure assignment doesn't work properly for PIC +- no built-in vararg support [shouldn't be too hard to add] + +The way most modern CPUs create the stack is to allocate the frame +to contain room for the temporaries, to save the permanent registers +and to store the arguments to functions invoked from within the function. +To achieve this, all the information must be known when the prologue +is generated. Currently we only know the size of the temporaries - +we don't know the size of the argument space for each function that +gets invoked from this function. Even if we did know this information, +we create ops to save the register arguments (R3-R10), early in pass1 +and don't know the position of the stack pointer, and the size of the +argument space required to "step over". + +One solution is to have two pointers to the stack. One for the top +of the stack and the other pointing just below the temporaries but above +the argument space. Then our function arguments and the permanent registers can +be saved fixed-relative to this register. If we don't know the size of +argument space, we cannot "dynamically" alter the stack (like we do with mips), +since the powerpc ABI specifies that the "lowest" address +in the stack frame is the saved stack pointer (pointing to the previous +stack frame). While this is a nice feature for tracking back through the +stack frames (which mips has always had problems with), it makes it +next-to-impossible to increase the strack frame dynamically. + +I guess the best approach is to determine the size of the argument stack +and have a second frame pointer. diff --git a/compilers/pcc/pcc-1.0.0/arch/powerpc/code.c b/compilers/pcc/pcc-1.0.0/arch/powerpc/code.c new file mode 100644 index 00000000..95248e75 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/powerpc/code.c @@ -0,0 +1,1541 @@ +/* $Id: code.c,v 1.23 2010/11/26 17:06:31 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "pass1.h" +#include "pass2.h" + +static void genswitch_bintree(int num, TWORD ty, struct swents **p, int n); + +#if 0 +static void genswitch_table(int num, struct swents **p, int n); +static void genswitch_mrst(int num, struct swents **p, int n); +#endif + +int lastloc = -1; +static int rvnr; + +/* + * Define everything needed to print out some data (or text). + * This means segment, alignment, visibility, etc. + */ +void +defloc(struct symtab *sp) +{ +#if defined(ELFABI) + static char *loctbl[] = { "text", "data", "rodata" }; +#elif defined(MACHOABI) + static char *loctbl[] = { "text", "data", "const_data" }; +#endif + TWORD t; + char *name; + int s, n; + + if (sp == NULL) { + lastloc = -1; + return; + } + t = sp->stype; + s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA; + if (s != lastloc) + printf(" .%s\n", loctbl[s]); + lastloc = s; + + if (s == PROG) + n = 2; + else if ((n = ispow2(talign(t, sp->sap) / SZCHAR)) == -1) + cerror("defalign: n != 2^i"); + printf(" .p2align %d\n", n); + + name = sp->soname ? sp->soname : exname(sp->sname); + if (sp->sclass == EXTDEF) + printf(" .globl %s\n", name); + if (sp->slevel == 0) + printf("%s:\n", name); + else + printf(LABFMT ":\n", sp->soffset); +} + +/* Put a symbol in a temporary + * used by bfcode() and its helpers + */ +static void +putintemp(struct symtab *sym) +{ + NODE *p; + + p = tempnode(0, sym->stype, sym->sdf, sym->sap); + p = buildtree(ASSIGN, p, nametree(sym)); + sym->soffset = regno(p->n_left); + sym->sflags |= STNODE; + ecomp(p); +} + +/* setup a 64-bit parameter (double/ldouble/longlong) + * used by bfcode() */ +static void +param_64bit(struct symtab *sym, int *argofsp, int dotemps) +{ + int argofs = *argofsp; + NODE *p, *q; + int navail; + +#if ALLONGLONG == 64 + /* alignment */ + ++argofs; + argofs &= ~1; +#endif + + navail = NARGREGS - argofs; + + if (navail < 2) { + /* half in and half out of the registers */ + q = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + regno(q) = R3 + argofs; + p = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + regno(p) = FPREG; + p = block(PLUS, p, bcon(sym->soffset/SZCHAR), PTR+INT, 0, MKAP(INT)); + p = block(UMUL, p, NIL, INT, 0, MKAP(INT)); + } else { + q = block(REG, NIL, NIL, sym->stype, sym->sdf, sym->sap); + regno(q) = R3R4 + argofs; + if (dotemps) { + p = tempnode(0, sym->stype, sym->sdf, sym->sap); + sym->soffset = regno(p); + sym->sflags |= STNODE; + } else { + p = nametree(sym); + } + } + p = buildtree(ASSIGN, p, q); + ecomp(p); + *argofsp = argofs + 2; +} + +/* setup a 32-bit param on the stack + * used by bfcode() */ +static void +param_32bit(struct symtab *sym, int *argofsp, int dotemps) +{ + NODE *p, *q; + + q = block(REG, NIL, NIL, sym->stype, sym->sdf, sym->sap); + regno(q) = R3 + (*argofsp)++; + if (dotemps) { + p = tempnode(0, sym->stype, sym->sdf, sym->sap); + sym->soffset = regno(p); + sym->sflags |= STNODE; + } else { + p = nametree(sym); + } + p = buildtree(ASSIGN, p, q); + ecomp(p); +} + +/* setup a double param on the stack + * used by bfcode() */ +static void +param_double(struct symtab *sym, int *argofsp, int dotemps) +{ + NODE *p, *q, *t; + int tmpnr; + + /* + * we have to dump the double from the general register + * into a temp, since the register allocator doesn't like + * floats to be in CLASSA. This may not work for -xtemps. + */ + + if (xtemps) { + q = block(REG, NIL, NIL, ULONGLONG, 0, MKAP(ULONGLONG)); + regno(q) = R3R4 + *argofsp; + p = block(REG, NIL, NIL, PTR+ULONGLONG, 0, MKAP(ULONGLONG)); + regno(p) = SPREG; + p = block(PLUS, p, bcon(-8), INT, 0, MKAP(INT)); + p = block(UMUL, p, NIL, ULONGLONG, 0, MKAP(ULONGLONG)); + p = buildtree(ASSIGN, p, q); + ecomp(p); + + t = tempnode(0, sym->stype, sym->sdf, sym->sap); + tmpnr = regno(t); + p = block(REG, NIL, NIL, + INCREF(sym->stype), sym->sdf, sym->sap); + regno(p) = SPREG; + p = block(PLUS, p, bcon(-8), INT, 0, MKAP(INT)); + p = block(UMUL, p, NIL, sym->stype, sym->sdf, sym->sap); + p = buildtree(ASSIGN, t, p); + ecomp(p); + } else { + /* bounce straight into temp */ + p = block(REG, NIL, NIL, ULONGLONG, 0, MKAP(ULONGLONG)); + regno(p) = R3R4 + *argofsp; + t = tempnode(0, ULONGLONG, 0, MKAP(ULONGLONG)); + tmpnr = regno(t); + p = buildtree(ASSIGN, t, p); + ecomp(p); + } + + (*argofsp) += 2; + + sym->soffset = tmpnr; + sym->sflags |= STNODE; +} + +/* setup a float param on the stack + * used by bfcode() */ +static void +param_float(struct symtab *sym, int *argofsp, int dotemps) +{ + NODE *p, *q, *t; + int tmpnr; + + /* + * we have to dump the float from the general register + * into a temp, since the register allocator doesn't like + * floats to be in CLASSA. This may not work for -xtemps. + */ + + if (xtemps) { + /* bounce onto TOS */ + q = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + regno(q) = R3 + (*argofsp); + p = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + regno(p) = SPREG; + p = block(PLUS, p, bcon(-4), INT, 0, MKAP(INT)); + p = block(UMUL, p, NIL, INT, 0, MKAP(INT)); + p = buildtree(ASSIGN, p, q); + ecomp(p); + + t = tempnode(0, sym->stype, sym->sdf, sym->sap); + tmpnr = regno(t); + p = block(REG, NIL, NIL, INCREF(sym->stype), + sym->sdf, sym->sap); + regno(p) = SPREG; + p = block(PLUS, p, bcon(-4), INT, 0, MKAP(INT)); + p = block(UMUL, p, NIL, sym->stype, sym->sdf, sym->sap); + p = buildtree(ASSIGN, t, p); + ecomp(p); + } else { + /* bounce straight into temp */ + p = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + regno(p) = R3 + (*argofsp); + t = tempnode(0, INT, 0, MKAP(INT)); + tmpnr = regno(t); + p = buildtree(ASSIGN, t, p); + ecomp(p); + } + + (*argofsp)++; + + sym->soffset = tmpnr; + sym->sflags |= STNODE; +} + +/* setup the hidden pointer to struct return parameter + * used by bfcode() */ +static void +param_retstruct(void) +{ + NODE *p, *q; + + p = tempnode(0, INCREF(cftnsp->stype), 0, cftnsp->sap); + rvnr = regno(p); + q = block(REG, NIL, NIL, INCREF(cftnsp->stype), + cftnsp->sdf, cftnsp->sap); + regno(q) = R3; + p = buildtree(ASSIGN, p, q); + ecomp(p); +} + + +/* setup struct parameter + * push the registers out to memory + * used by bfcode() */ +static void +param_struct(struct symtab *sym, int *argofsp) +{ + int argofs = *argofsp; + NODE *p, *q; + int navail; + int sz; + int off; + int num; + int i; + + navail = NARGREGS - argofs; + sz = tsize(sym->stype, sym->sdf, sym->sap) / SZINT; + off = ARGINIT/SZINT + argofs; + num = sz > navail ? navail : sz; + for (i = 0; i < num; i++) { + q = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + regno(q) = R3 + argofs++; + p = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + regno(p) = SPREG; + p = block(PLUS, p, bcon(4*off++), INT, 0, MKAP(INT)); + p = block(UMUL, p, NIL, INT, 0, MKAP(INT)); + p = buildtree(ASSIGN, p, q); + ecomp(p); + } + + *argofsp = argofs; +} + +/* + * code for the beginning of a function + * sp is an array of indices in symtab for the arguments + * cnt is the number of arguments + */ +void +bfcode(struct symtab **sp, int cnt) +{ +#ifdef USE_GOTNR + extern int gotnr; +#endif + + struct symtab *sp2; + union arglist *usym; + int saveallargs = 0; + int i, argofs = 0; + + /* + * Detect if this function has ellipses and save all + * argument registers onto stack. + */ + usym = cftnsp->sdf->dfun; + while (usym && usym->type != TNULL) { + if (usym->type == TELLIPSIS) { + saveallargs = 1; + break; + } + ++usym; + } + + if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) { + param_retstruct(); + ++argofs; + } + +#ifdef USE_GOTNR + if (kflag) { + /* put GOT register into temporary */ + NODE *q, *p; + q = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + regno(q) = GOTREG; + p = tempnode(0, INT, 0, MKAP(INT)); + gotnr = regno(p); + ecomp(buildtree(ASSIGN, p, q)); + } +#endif + + /* recalculate the arg offset and create TEMP moves */ + for (i = 0; i < cnt; i++) { + + if (sp[i] == NULL) + continue; + + if ((argofs >= NARGREGS) && !xtemps) + break; + + if (argofs >= NARGREGS) { + putintemp(sp[i]); + } else if (sp[i]->stype == STRTY || sp[i]->stype == UNIONTY) { + param_struct(sp[i], &argofs); + } else if (DEUNSIGN(sp[i]->stype) == LONGLONG) { + param_64bit(sp[i], &argofs, xtemps && !saveallargs); + } else if (sp[i]->stype == DOUBLE || sp[i]->stype == LDOUBLE) { + if (features(FEATURE_HARDFLOAT)) + param_double(sp[i], &argofs, + xtemps && !saveallargs); + else + param_64bit(sp[i], &argofs, + xtemps && !saveallargs); + } else if (sp[i]->stype == FLOAT) { + if (features(FEATURE_HARDFLOAT)) + param_float(sp[i], &argofs, + xtemps && !saveallargs); + else + param_32bit(sp[i], &argofs, + xtemps && !saveallargs); + } else { + param_32bit(sp[i], &argofs, xtemps && !saveallargs); + } + } + + /* if saveallargs, save the rest of the args onto the stack */ + while (saveallargs && argofs < NARGREGS) { + NODE *p, *q; + /* int off = (ARGINIT+FIXEDSTACKSIZE*SZCHAR)/SZINT + argofs; */ + int off = ARGINIT/SZINT + argofs; + q = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + regno(q) = R3 + argofs++; + p = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + regno(p) = FPREG; + p = block(PLUS, p, bcon(4*off), INT, 0, MKAP(INT)); + p = block(UMUL, p, NIL, INT, 0, MKAP(INT)); + p = buildtree(ASSIGN, p, q); + ecomp(p); + } + + /* profiling */ + if (pflag) { + NODE *p; + +#if defined(ELFABI) + + sp2 = lookup("_mcount", 0); + sp2->stype = EXTERN; + p = nametree(sp2); + p->n_sp->sclass = EXTERN; + p = clocal(p); + p = buildtree(ADDROF, p, NIL); + p = block(UCALL, p, NIL, INT, 0, MKAP(INT)); + ecomp(funcode(p)); + + +#elif defined(MACHOABI) + + NODE *q; + int tmpnr; + + q = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + regno(q) = R0; + p = tempnode(0, INT, 0, MKAP(INT)); + tmpnr = regno(p); + p = buildtree(ASSIGN, p, q); + ecomp(p); + + q = tempnode(tmpnr, INT, 0, MKAP(INT)); + + sp2 = lookup("mcount", 0); + sp2->stype = EXTERN; + p = nametree(sp2); + p->n_sp->sclass = EXTERN; + p = clocal(p); + p = buildtree(ADDROF, p, NIL); + p = block(CALL, p, q, INT, 0, MKAP(INT)); + ecomp(funcode(p)); + +#endif + } +} + +/* + * code for the end of a function + * deals with struct return here + */ +void +efcode() +{ + NODE *p, *q; + int tempnr; + int ty; + +#ifdef USE_GOTNR + extern int gotnr; + gotnr = 0; +#endif + + if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) + return; + + ty = cftnsp->stype - FTN; + + q = block(REG, NIL, NIL, INCREF(ty), 0, cftnsp->sap); + regno(q) = R3; + p = tempnode(0, INCREF(ty), 0, cftnsp->sap); + tempnr = regno(p); + p = buildtree(ASSIGN, p, q); + ecomp(p); + + q = tempnode(tempnr, INCREF(ty), 0, cftnsp->sap); + q = buildtree(UMUL, q, NIL); + + p = tempnode(rvnr, INCREF(ty), 0, cftnsp->sap); + p = buildtree(UMUL, p, NIL); + + p = buildtree(ASSIGN, p, q); + ecomp(p); + + q = tempnode(rvnr, INCREF(ty), 0, cftnsp->sap); + p = block(REG, NIL, NIL, INCREF(ty), 0, cftnsp->sap); + regno(p) = R3; + p = buildtree(ASSIGN, p, q); + ecomp(p); +} + +/* + * by now, the automatics and register variables are allocated + */ +void +bccode() +{ + SETOFF(autooff, SZINT); +} + +struct stub stublist; +struct stub nlplist; + +/* called just before final exit */ +/* flag is 1 if errors, 0 if none */ +void +ejobcode(int flag ) +{ + +#if defined(MACHOABI) + /* + * iterate over the stublist and output the PIC stubs +` */ + if (kflag) { + struct stub *p; + + DLIST_FOREACH(p, &stublist, link) { + printf("\t.section __TEXT, __picsymbolstub1,symbol_stubs,pure_instructions,32\n"); + printf("\t.align 5\n"); + printf("L%s$stub:\n", p->name); + if (strcmp(p->name, "mcount") == 0) + printf("\t.indirect_symbol %s\n", p->name); + else + printf("\t.indirect_symbol %s\n", p->name); + printf("\tmflr r0\n"); + printf("\tbcl 20,31,L%s$spb\n", p->name); + printf("L%s$spb:\n", p->name); + printf("\tmflr r11\n"); + printf("\taddis r11,r11,ha16(L%s$lazy_ptr-L%s$spb)\n", + p->name, p->name); + printf("\tmtlr r0\n"); + printf("\tlwzu r12,lo16(L%s$lazy_ptr-L%s$spb)(r11)\n", + p->name, p->name); + printf("\tmtctr r12\n"); + printf("\tbctr\n"); + printf("\t.lazy_symbol_pointer\n"); + printf("L%s$lazy_ptr:\n", p->name); + if (strcmp(p->name, "mcount") == 0) + printf("\t.indirect_symbol %s\n", p->name); + else + printf("\t.indirect_symbol %s\n", p->name); + printf("\t.long dyld_stub_binding_helper\n"); + printf("\t.subsections_via_symbols\n"); + } + + printf("\t.non_lazy_symbol_pointer\n"); + DLIST_FOREACH(p, &nlplist, link) { + printf("L%s$non_lazy_ptr:\n", p->name); + if (strcmp(p->name, "mcount") == 0) + printf("\t.indirect_symbol %s\n", p->name); + else + printf("\t.indirect_symbol %s\n", p->name); + printf("\t.long 0\n"); + } + + } +#endif + +#ifndef os_darwin +#define _MKSTR(x) #x +#define MKSTR(x) _MKSTR(x) +#define OS MKSTR(TARGOS) + printf("\t.ident \"PCC: %s (%s)\"\n", PACKAGE_STRING, OS); +#endif + +} + +void +bjobcode() +{ + DLIST_INIT(&stublist, link); + DLIST_INIT(&nlplist, link); +} + +#ifdef notdef +/* + * Print character t at position i in one string, until t == -1. + * Locctr & label is already defined. + */ +void +bycode(int t, int i) +{ + static int lastoctal = 0; + + /* put byte i+1 in a string */ + + if (t < 0) { + if (i != 0) + puts("\""); + } else { + if (i == 0) + printf("\t.ascii \""); + if (t == '\\' || t == '"') { + lastoctal = 0; + putchar('\\'); + putchar(t); + } else if (t < 040 || t >= 0177) { + lastoctal++; + printf("\\%o",t); + } else if (lastoctal && '0' <= t && t <= '9') { + lastoctal = 0; + printf("\"\n\t.ascii \"%c", t); + } else { + lastoctal = 0; + putchar(t); + } + } +} +#endif + +/* + * return the alignment of field of type t + */ +int +fldal(unsigned int t) +{ + uerror("fldal: illegal field type"); + return(ALINT); +} + +/* fix up type of field p */ +void +fldty(struct symtab *p) +{ +} + +/* + * XXX - fix genswitch. + */ +int +mygenswitch(int num, TWORD type, struct swents **p, int n) +{ + if (num < 0) { + genswitch_bintree(num, type, p, n); + return 1; + } + + return 0; + +#if 0 + if (0) + genswitch_table(num, p, n); + if (0) + genswitch_bintree(num, p, n); + genswitch_mrst(num, p, n); +#endif +} + +static void bintree_rec(TWORD ty, int num, + struct swents **p, int n, int s, int e); + +static void +genswitch_bintree(int num, TWORD ty, struct swents **p, int n) +{ + int lab = getlab(); + + if (p[0]->slab == 0) + p[0]->slab = lab; + + bintree_rec(ty, num, p, n, 1, n); + + plabel(lab); +} + +static void +bintree_rec(TWORD ty, int num, struct swents **p, int n, int s, int e) +{ + NODE *r; + int rlabel; + int h; + + if (s == e) { + r = tempnode(num, ty, 0, MKAP(ty)); + r = buildtree(NE, r, bcon(p[s]->sval)); + cbranch(buildtree(NOT, r, NIL), bcon(p[s]->slab)); + branch(p[0]->slab); + return; + } + + rlabel = getlab(); + + h = s + (e - s) / 2; + + r = tempnode(num, ty, 0, MKAP(ty)); + r = buildtree(GT, r, bcon(p[h]->sval)); + cbranch(r, bcon(rlabel)); + bintree_rec(ty, num, p, n, s, h); + plabel(rlabel); + bintree_rec(ty, num, p, n, h+1, e); +} + + +#if 0 + +static void +genswitch_table(int num, struct swents **p, int n) +{ + NODE *r, *t; + int tval; + int minval, maxval, range; + int deflabel, tbllabel; + int i, j; + + minval = p[1]->sval; + maxval = p[n]->sval; + + range = maxval - minval + 1; + + if (n < 10 || range > 3 * n) { + /* too small or too sparse for jump table */ + genswitch_simple(num, p, n); + return; + } + + r = tempnode(num, UNSIGNED, 0, MKAP(UNSIGNED)); + r = buildtree(MINUS, r, bcon(minval)); + t = tempnode(0, UNSIGNED, 0, MKAP(UNSIGNED)); + tval = regno(t); + r = buildtree(ASSIGN, t, r); + ecomp(r); + + deflabel = p[0]->slab; + if (deflabel == 0) + deflabel = getlab(); + + t = tempnode(tval, UNSIGNED, 0, MKAP(UNSIGNED)); + cbranch(buildtree(GT, t, bcon(maxval-minval)), bcon(deflabel)); + + tbllabel = getlab(); + struct symtab *strtbl = lookup("__switch_table", SLBLNAME|STEMP); + strtbl->soffset = tbllabel; + strtbl->sclass = ILABEL; + strtbl->stype = INCREF(UCHAR); + + t = block(NAME, NIL, NIL, UNSIGNED, 0, MKAP(UNSIGNED)); + t->n_sp = strtbl; + t = buildtree(ADDROF, t, NIL); + r = tempnode(tval, UNSIGNED, 0, MKAP(INT)); + r = buildtree(PLUS, t, r); + t = tempnode(0, INCREF(UNSIGNED), 0, MKAP(UNSIGNED)); + r = buildtree(ASSIGN, t, r); + ecomp(r); + + r = tempnode(regno(t), INCREF(UNSIGNED), 0, MKAP(UNSIGNED)); + r = buildtree(UMUL, r, NIL); + t = block(NAME, NIL, NIL, UCHAR, 0, MKAP(UCHAR)); + t->n_sp = strtbl; + t = buildtree(ADDROF, t, NIL); + r = buildtree(PLUS, t, r); + r = block(GOTO, r, NIL, 0, 0, 0); + ecomp(r); + + plabel(tbllabel); + for (i = minval, j=1; i <= maxval; i++) { + char *entry = tmpalloc(20); + int lab = deflabel; + //printf("; minval=%d, maxval=%d, i=%d, j=%d p[j]=%lld\n", minval, maxval, i, j, p[j]->sval); + if (p[j]->sval == i) { + lab = p[j]->slab; + j++; + } + snprintf(entry, 20, ".long " LABFMT "-" LABFMT, lab, tbllabel); + send_passt(IP_ASM, entry); + } + + if (p[0]->slab <= 0) + plabel(deflabel); +} + +#define DPRINTF(x) if (xdebug) printf x +//#define DPRINTF(x) do { } while(0) + +#define MIN_TABLE_SIZE 8 + +/* + * Multi-way Radix Search Tree (MRST) + */ + +static void mrst_rec(int num, struct swents **p, int n, int *state, int lab); +static unsigned long mrst_find_window(struct swents **p, int n, int *state, int lab, int *len, int *lowbit); +void mrst_put_entry_and_recurse(int num, struct swents **p, int n, int *state, int tbllabel, int lab, unsigned long j, unsigned long tblsize, unsigned long Wmax, int lowbit); + +static void +genswitch_mrst(int num, struct swents **p, int n) +{ + int *state; + int i; + int putlabel = 0; + + if (n < 10) { + /* too small for MRST */ + genswitch_simple(num, p, n); + return; + } + + state = tmpalloc((n+1)*sizeof(int)); + for (i = 0; i <= n; i++) + state[i] = 0; + + if (p[0]->slab == 0) { + p[0]->slab = getlab(); + putlabel = 1; + } + + mrst_rec(num, p, n, state, 0); + + if (putlabel) + plabel(p[0]->slab); +} + + +/* + * Look through the cases and generate a table or + * list of simple comparisons. If generating a table, + * invoke mrst_put_entry_and_recurse() to put + * an entry in the table and recurse. + */ +static void +mrst_rec(int num, struct swents **p, int n, int *state, int lab) +{ + int len, lowbit; + unsigned long Wmax; + unsigned int tblsize; + NODE *t; + NODE *r; + int tval; + int i; + + DPRINTF(("mrst_rec: num=%d, n=%d, lab=%d\n", num, n, lab)); + + /* find best window to cover set*/ + Wmax = mrst_find_window(p, n, state, lab, &len, &lowbit); + tblsize = (1 << len); + assert(len > 0 && tblsize > 0); + + DPRINTF(("mrst_rec: Wmax=%lu, lowbit=%d, tblsize=%u\n", + Wmax, lowbit, tblsize)); + + if (lab) + plabel(lab); + + if (tblsize <= MIN_TABLE_SIZE) { + DPRINTF(("msrt_rec: break the recursion\n")); + for (i = 1; i <= n; i++) { + if (state[i] == lab) { + t = tempnode(num, UNSIGNED, 0, MKAP(UNSIGNED)); + cbranch(buildtree(EQ, t, bcon(p[i]->sval)), + bcon(p[i]->slab)); + } + } + branch(p[0]->slab); + return; + } + + DPRINTF(("generating table with %d elements\n", tblsize)); + + // AND with Wmax + t = tempnode(num, UNSIGNED, 0, MKAP(UNSIGNED)); + r = buildtree(AND, t, bcon(Wmax)); + + // RS lowbits + r = buildtree(RS, r, bcon(lowbit)); + + t = tempnode(0, UNSIGNED, 0, MKAP(UNSIGNED)); + tval = regno(t); + r = buildtree(ASSIGN, t, r); + ecomp(r); + + int tbllabel = getlab(); + struct symtab *strtbl = lookup("__switch_table", SLBLNAME|STEMP); + strtbl->sclass = STATIC; + strtbl->sap = MKAP(UCHAR); + strtbl->slevel = 1; + strtbl->soffset = tbllabel; + strtbl->stype = INCREF(UCHAR); + strtbl->squal = (CON >> TSHIFT); + + t = block(NAME, NIL, NIL, UNSIGNED, 0, MKAP(UNSIGNED)); + t->n_sp = strtbl; + t = buildtree(ADDROF, t, NIL); + r = tempnode(tval, UNSIGNED, 0, MKAP(INT)); + r = buildtree(PLUS, t, r); + t = tempnode(0, INCREF(UNSIGNED), 0, MKAP(UNSIGNED)); + r = buildtree(ASSIGN, t, r); + ecomp(r); + + r = tempnode(regno(t), INCREF(UNSIGNED), 0, MKAP(UNSIGNED)); + r = buildtree(UMUL, r, NIL); + t = block(NAME, NIL, NIL, UCHAR, 0, MKAP(UCHAR)); + t->n_sp = strtbl; + t = buildtree(ADDROF, t, NIL); + r = buildtree(PLUS, t, r); + r = block(GOTO, r, NIL, 0, 0, 0); + ecomp(r); + + plabel(tbllabel); + + mrst_put_entry_and_recurse(num, p, n, state, tbllabel, lab, + 0, tblsize, Wmax, lowbit); +} + + +/* + * Put an entry into the table and recurse to the next entry + * in the table. On the way back through the recursion, invoke + * mrst_rec() to check to see if we should generate another + * table. + */ +void +mrst_put_entry_and_recurse(int num, struct swents **p, int n, int *state, + int tbllabel, int labval, + unsigned long j, unsigned long tblsize, unsigned long Wmax, int lowbit) +{ + int i; + int found = 0; + int lab = getlab(); + + /* + * Look for labels which map to this table entry. + * Mark each one in "state" that they fall inside this table. + */ + for (i = 1; i <= n; i++) { + unsigned int val = (p[i]->sval & Wmax) >> lowbit; + if (val == j && state[i] == labval) { + found = 1; + state[i] = lab; + } + } + + /* couldn't find any labels? goto the default label */ + if (!found) + lab = p[0]->slab; + + /* generate the table entry */ + char *entry = tmpalloc(20); + snprintf(entry, 20, ".long " LABFMT "-" LABFMT, lab, tbllabel); + send_passt(IP_ASM, entry); + + DPRINTF(("mrst_put_entry: table=%d, pos=%lu/%lu, label=%d\n", + tbllabel, j, tblsize, lab)); + + /* go to the next table entry */ + if (j+1 < tblsize) { + mrst_put_entry_and_recurse(num, p, n, state, tbllabel, labval, + j+1, tblsize, Wmax, lowbit); + } + + /* if we are going to the default label, bail now */ + if (!found) + return; + +#ifdef PCC_DEBUG + if (xdebug) { + printf("state: "); + for (i = 1; i <= n; i++) + printf("%d ", state[i]); + printf("\n"); + } +#endif + + /* build another table */ + mrst_rec(num, p, n, state, lab); +} + +/* + * counts the number of entries in a table of size (1 << L) which would + * be used given the cases and the mask (W, lowbit). + */ +static unsigned int +mrst_cardinality(struct swents **p, int n, int *state, int step, unsigned long W, int L, int lowbit) +{ + unsigned int count = 0; + int i; + + if (W == 0) + return 0; + + int *vals = (int *)calloc(1 << L, sizeof(int)); + assert(vals); + + DPRINTF(("mrst_cardinality: ")); + for (i = 1; i <= n; i++) { + int idx; + if (state[i] != step) + continue; + idx = (p[i]->sval & W) >> lowbit; + DPRINTF(("%llu->%d, ", p[i]->sval, idx)); + if (!vals[idx]) { + count++; + } + vals[idx] = 1; + } + DPRINTF((": found %d entries\n", count)); + free(vals); + + return count; +} + +/* + * Find the maximum window (table size) which would best cover + * the set of labels. Algorithm explained in: + * + * Ulfar Erlingsson, Mukkai Krishnamoorthy and T.V. Raman. + * Efficient Multiway Radix Search Trees. + * Information Processing Letters 60:3 115-120 (November 1996) + */ + +static unsigned long +mrst_find_window(struct swents **p, int n, int *state, int lab, int *len, int *lowbit) +{ + unsigned int tblsize; + unsigned long W = 0; + unsigned long Wmax = 0; + unsigned long Wleft = (1 << (SZLONG-1)); + unsigned int C = 0; + unsigned int Cmax = 0; + int L = 0; + int Lmax = 0; + int lowmax = 0; + int no_b = SZLONG-1; + unsigned long b = (1 << (SZLONG-1)); + + DPRINTF(("mrst_find_window: n=%d, lab=%d\n", n, lab)); + + for (; b > 0; b >>= 1, no_b--) { + + // select the next bit + W |= b; + L += 1; + + tblsize = 1 << L; + assert(tblsize > 0); + + DPRINTF(("no_b=%d, b=0x%lx, Wleft=0x%lx, W=0x%lx, Wmax=0x%lx, L=%d, Lmax=%d, Cmax=%u, lowmax=%d, tblsize=%u\n", no_b, b, Wleft, W, Wmax, L, Lmax, Cmax, lowmax, tblsize)); + + C = mrst_cardinality(p, n, state, lab, W, L, no_b); + DPRINTF((" -> cardinality is %d\n", C)); + + if (2*C >= tblsize) { + DPRINTF(("(found good match, keep adding to table)\n")); + Wmax = W; + Lmax = L; + lowmax = no_b; + Cmax = C; + } else { + DPRINTF(("(too sparse)\n")); + assert((W & Wleft) != 0); + + /* flip the MSB and see if we get a better match */ + W ^= Wleft; + Wleft >>= 1; + L -= 1; + + DPRINTF((" --> trying W=0x%lx and L=%d and Cmax=%u\n", W, L, Cmax)); + C = mrst_cardinality(p, n, state, lab, W, L, no_b); + DPRINTF((" --> C=%u\n", C)); + if (C > Cmax) { + Wmax = W; + Lmax = L; + lowmax = no_b; + Cmax = C; + DPRINTF((" --> better!\n")); + } else { + DPRINTF((" --> no better\n")); + } + } + + } + +#ifdef PCC_DEBUG + if (xdebug) { + int i; + int hibit = lowmax + Lmax; + printf("msrt_find_window: Wmax=0x%lx, lowbit=%d, result=", Wmax, lowmax); + for (i = 31; i >= 0; i--) { + int mask = (1 << i); + if (i == hibit) + printf("["); + if (Wmax & mask) + printf("1"); + else + printf("0"); + if (i == lowmax) + printf("]"); + } + printf("\n"); + } +#endif + + assert(Lmax > 0); + *len = Lmax; + *lowbit = lowmax; + + DPRINTF(("msrt_find_window: returning Wmax=%lu, len=%d, lowbit=%d [tblsize=%u, entries=%u]\n", Wmax, Lmax, lowmax, tblsize, C)); + + return Wmax; +} +#endif + +/* + * Straighten a chain of CM ops so that the CM nodes + * only appear on the left node. + * + * CM CM + * CM CM CM b + * x y a b CM a + * x y + * + * CM CM + * CM CM CM c + * CM z CM c CM b + * x y a b CM a + * CM z + * x y + */ +static NODE * +straighten(NODE *p) +{ + NODE *r = p->n_right; + + if (p->n_op != CM || r->n_op != CM) + return p; + + p->n_right = r->n_left; + r->n_left = straighten(p); + + return r; +} + +static NODE * +reverse1(NODE *p, NODE *a) +{ + NODE *l = p->n_left; + NODE *r = p->n_right; + + a->n_right = r; + p->n_left = a; + + if (l->n_op == CM) { + return reverse1(l, p); + } else { + p->n_right = l; + return p; + } +} + +/* + * Reverse a chain of CM ops + */ +static NODE * +reverse(NODE *p) +{ + NODE *l = p->n_left; + NODE *r = p->n_right; + + p->n_left = r; + + if (l->n_op == CM) + return reverse1(l, p); + + p->n_right = l; + + return p; +} + +/* push arg onto the stack */ +/* called by moveargs() */ +static NODE * +pusharg(NODE *p, int *regp) +{ + NODE *q; + int sz; + int off; + + /* convert to register size, if smaller */ + sz = tsize(p->n_type, p->n_df, p->n_ap); + if (sz < SZINT) + p = block(SCONV, p, NIL, INT, 0, MKAP(INT)); + + q = block(REG, NIL, NIL, INCREF(p->n_type), p->n_df, p->n_ap); + regno(q) = SPREG; + + off = ARGINIT/SZCHAR + 4 * (*regp - R3); + q = block(PLUS, q, bcon(off), INT, 0, MKAP(INT)); + q = block(UMUL, q, NIL, p->n_type, p->n_df, p->n_ap); + (*regp) += szty(p->n_type); + + return buildtree(ASSIGN, q, p); +} + +/* setup call stack with 32-bit argument */ +/* called from moveargs() */ +static NODE * +movearg_32bit(NODE *p, int *regp) +{ + int reg = *regp; + NODE *q; + + q = block(REG, NIL, NIL, p->n_type, p->n_df, p->n_ap); + regno(q) = reg++; + q = buildtree(ASSIGN, q, p); + + *regp = reg; + return q; +} + +/* setup call stack with 64-bit argument */ +/* called from moveargs() */ +static NODE * +movearg_64bit(NODE *p, int *regp) +{ + int reg = *regp; + NODE *q, *r; + +#if ALLONGLONG == 64 + /* alignment */ + ++reg; + reg &= ~1; +#endif + + if (reg > R10) { + *regp = reg; + q = pusharg(p, regp); + } else if (reg == R10) { + /* half in and half out of the registers */ + r = tcopy(p); + if (!features(FEATURE_BIGENDIAN)) { + q = block(SCONV, p, NIL, INT, 0, MKAP(INT)); + q = movearg_32bit(q, regp); /* little-endian */ + r = buildtree(RS, r, bcon(32)); + r = block(SCONV, r, NIL, INT, 0, MKAP(INT)); + r = pusharg(r, regp); /* little-endian */ + } else { + q = buildtree(RS, p, bcon(32)); + q = block(SCONV, q, NIL, INT, 0, MKAP(INT)); + q = movearg_32bit(q, regp); /* big-endian */ + r = block(SCONV, r, NIL, INT, 0, MKAP(INT)); + r = pusharg(r, regp); /* big-endian */ + } + q = straighten(block(CM, q, r, p->n_type, p->n_df, p->n_ap)); + } else { + q = block(REG, NIL, NIL, p->n_type, p->n_df, p->n_ap); + regno(q) = R3R4 + (reg - R3); + q = buildtree(ASSIGN, q, p); + *regp = reg + 2; + } + + return q; +} + +/* setup call stack with float argument */ +/* called from moveargs() */ +static NODE * +movearg_float(NODE *p, int *fregp, int *regp) +{ +#if defined(MACHOABI) + NODE *q, *r; + TWORD ty = INCREF(p->n_type); + int tmpnr; +#endif + + p = movearg_32bit(p, fregp); + + /* + * On OS/X, floats are passed in the floating-point registers + * and in the general registers for compatibily with libraries + * compiled to handle soft-float. + */ + +#if defined(MACHOABI) + + if (xtemps) { + /* bounce into TOS */ + r = block(REG, NIL, NIL, ty, p->n_df, p->n_ap); + regno(r) = SPREG; + r = block(PLUS, r, bcon(-4), INT, 0, MKAP(INT)); + r = block(UMUL, r, NIL, p->n_type, p->n_df, p->n_ap); + r = buildtree(ASSIGN, r, p); + ecomp(r); + + /* bounce into temp */ + r = block(REG, NIL, NIL, PTR+INT, 0, MKAP(INT)); + regno(r) = SPREG; + r = block(PLUS, r, bcon(-4), INT, 0, MKAP(INT)); + r = block(UMUL, r, NIL, INT, 0, MKAP(INT)); + q = tempnode(0, INT, 0, MKAP(INT)); + tmpnr = regno(q); + r = buildtree(ASSIGN, q, r); + ecomp(r); + } else { + /* copy directly into temp */ + q = tempnode(0, p->n_type, p->n_df, p->n_ap); + tmpnr = regno(q); + r = buildtree(ASSIGN, q, p); + ecomp(r); + } + + /* copy from temp to register parameter */ + r = tempnode(tmpnr, INT, 0, MKAP(INT)); + q = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + regno(q) = (*regp)++; + p = buildtree(ASSIGN, q, r); + +#endif + return p; + +} + +/* setup call stack with float/double argument */ +/* called from moveargs() */ +static NODE * +movearg_double(NODE *p, int *fregp, int *regp) +{ +#if defined(MACHOABI) + NODE *q, *r; + TWORD ty = INCREF(p->n_type); + int tmpnr; +#endif + + /* this does the move to a single register for us */ + p = movearg_32bit(p, fregp); + + /* + * On OS/X, doubles are passed in the floating-point registers + * and in the general registers for compatibily with libraries + * compiled to handle soft-float. + */ + +#if defined(MACHOABI) + + if (xtemps) { + /* bounce on TOS */ + r = block(REG, NIL, NIL, ty, p->n_df, p->n_ap); + regno(r) = SPREG; + r = block(PLUS, r, bcon(-8), ty, p->n_df, p->n_ap); + r = block(UMUL, r, NIL, p->n_type, p->n_df, p->n_ap); + r = buildtree(ASSIGN, r, p); + ecomp(r); + + /* bounce into temp */ + r = block(REG, NIL, NIL, PTR+LONGLONG, 0, MKAP(LONGLONG)); + regno(r) = SPREG; + r = block(PLUS, r, bcon(-8), PTR+LONGLONG, 0, MKAP(LONGLONG)); + r = block(UMUL, r, NIL, LONGLONG, 0, MKAP(LONGLONG)); + q = tempnode(0, LONGLONG, 0, MKAP(LONGLONG)); + tmpnr = regno(q); + r = buildtree(ASSIGN, q, r); + ecomp(r); + } else { + /* copy directly into temp */ + q = tempnode(0, p->n_type, p->n_df, p->n_ap); + tmpnr = regno(q); + r = buildtree(ASSIGN, q, p); + ecomp(r); + } + + /* copy from temp to register parameter */ + r = tempnode(tmpnr, LONGLONG, 0, MKAP(LONGLONG)); + q = block(REG, NIL, NIL, LONGLONG, 0, MKAP(LONGLONG)); + regno(q) = R3R4 - R3 + (*regp); + p = buildtree(ASSIGN, q, r); + + (*regp) += 2; + +#endif + + return p; +} + +/* setup call stack with a structure */ +/* called from moveargs() */ +static NODE * +movearg_struct(NODE *p, int *regp) +{ + int reg = *regp; + NODE *l, *q, *t, *r; + int tmpnr; + int navail; + int num; + int sz; + int ty; + int i; + + assert(p->n_op == STARG); + + navail = NARGREGS - (reg - R3); + navail = navail < 0 ? 0 : navail; + sz = tsize(p->n_type, p->n_df, p->n_ap) / SZINT; + num = sz > navail ? navail : sz; + + /* remove STARG node */ + l = p->n_left; + nfree(p); + ty = l->n_type; + + /* + * put it into a TEMP, rather than tcopy(), since the tree + * in p may have side-affects + */ + t = tempnode(0, ty, l->n_df, l->n_ap); + tmpnr = regno(t); + q = buildtree(ASSIGN, t, l); + + /* copy structure into registers */ + for (i = 0; i < num; i++) { + t = tempnode(tmpnr, ty, 0, MKAP(PTR+ty)); + t = block(SCONV, t, NIL, PTR+INT, 0, MKAP(PTR+INT)); + t = block(PLUS, t, bcon(4*i), PTR+INT, 0, MKAP(PTR+INT)); + t = buildtree(UMUL, t, NIL); + + r = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + regno(r) = reg++; + r = buildtree(ASSIGN, r, t); + + q = block(CM, q, r, INT, 0, MKAP(INT)); + } + + /* put the rest of the structure on the stack */ + for (i = num; i < sz; i++) { + t = tempnode(tmpnr, ty, 0, MKAP(PTR+ty)); + t = block(SCONV, t, NIL, PTR+INT, 0, MKAP(PTR+INT)); + t = block(PLUS, t, bcon(4*i), PTR+INT, 0, MKAP(PTR+INT)); + t = buildtree(UMUL, t, NIL); + r = pusharg(t, ®); + q = block(CM, q, r, INT, 0, MKAP(INT)); + } + + q = reverse(q); + + *regp = reg; + return q; +} + + +static NODE * +moveargs(NODE *p, int *regp, int *fregp) +{ + NODE *r, **rp; + int reg, freg; + + if (p->n_op == CM) { + p->n_left = moveargs(p->n_left, regp, fregp); + r = p->n_right; + rp = &p->n_right; + } else { + r = p; + rp = &p; + } + + reg = *regp; + freg = *fregp; + +#define ISFLOAT(p) (p->n_type == FLOAT || \ + p->n_type == DOUBLE || \ + p->n_type == LDOUBLE) + + if (reg > R10 && r->n_op != STARG) { + *rp = pusharg(r, regp); + } else if (r->n_op == STARG) { + *rp = movearg_struct(r, regp); + } else if (DEUNSIGN(r->n_type) == LONGLONG) { + *rp = movearg_64bit(r, regp); + } else if (r->n_type == DOUBLE || r->n_type == LDOUBLE) { + if (features(FEATURE_HARDFLOAT)) + *rp = movearg_double(r, fregp, regp); + else + *rp = movearg_64bit(r, regp); + } else if (r->n_type == FLOAT) { + if (features(FEATURE_HARDFLOAT)) + *rp = movearg_float(r, fregp, regp); + else + *rp = movearg_32bit(r, regp); + } else { + *rp = movearg_32bit(r, regp); + } + + return straighten(p); +} + +/* + * Fixup arguments to pass pointer-to-struct as first argument. + * + * called from funcode(). + */ +static NODE * +retstruct(NODE *p) +{ + struct symtab s; + NODE *l, *r, *t, *q; + TWORD ty; + + l = p->n_left; + r = p->n_right; + + ty = DECREF(l->n_type) - FTN; + + s.sclass = AUTO; + s.stype = ty; + s.sdf = l->n_df; + s.sap = l->n_ap; + oalloc(&s, &autooff); + q = block(REG, NIL, NIL, INCREF(ty), l->n_df, l->n_ap); + regno(q) = FPREG; + q = block(MINUS, q, bcon(autooff/SZCHAR), INCREF(ty), + l->n_df, l->n_ap); + + /* insert hidden assignment at beginning of list */ + if (r->n_op != CM) { + p->n_right = block(CM, q, r, INCREF(ty), l->n_df, l->n_ap); + } else { + for (t = r; t->n_left->n_op == CM; t = t->n_left) + ; + t->n_left = block(CM, q, t->n_left, INCREF(ty), + l->n_df, l->n_ap); + } + + return p; +} + +/* + * Called with a function call with arguments as argument. + * This is done early in buildtree() and only done once. + */ +NODE * +funcode(NODE *p) +{ + int regnum = R3; + int fregnum = F1; + + if (DECREF(p->n_left->n_type) == STRTY+FTN || + DECREF(p->n_left->n_type) == UNIONTY+FTN) + p = retstruct(p); + + p->n_right = moveargs(p->n_right, ®num, &fregnum); + + if (p->n_right == NULL) + p->n_op += (UCALL - CALL); + + return p; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/powerpc/local.c b/compilers/pcc/pcc-1.0.0/arch/powerpc/local.c new file mode 100644 index 00000000..e59fde7e --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/powerpc/local.c @@ -0,0 +1,1512 @@ +/* $Id: local.c,v 1.28 2011/01/21 21:47:59 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "pass1.h" + +#define IALLOC(sz) (isinlining ? permalloc(sz) : tmpalloc(sz)) + +extern int kflag; + +static void simmod(NODE *p); + +/* this file contains code which is dependent on the target machine */ + +#if defined(MACHOABI) + +/* + * Keep track of PIC stubs. + */ + +void +addstub(struct stub *list, char *name) +{ + struct stub *s; + + DLIST_FOREACH(s, list, link) { + if (strcmp(s->name, name) == 0) + return; + } + + s = permalloc(sizeof(struct stub)); + s->name = permalloc(strlen(name) + 1); + strcpy(s->name, name); + DLIST_INSERT_BEFORE(list, s, link); +} + +#endif + + +/* + * Make a symtab entry for PIC use. + */ +static struct symtab * +picsymtab(char *p, char *s, char *s2) +{ + struct symtab *sp = IALLOC(sizeof(struct symtab)); + size_t len = strlen(p) + strlen(s) + strlen(s2) + 1; + + sp->sname = sp->soname = IALLOC(len); + strlcpy(sp->soname, p, len); + strlcat(sp->soname, s, len); + strlcat(sp->soname, s2, len); + sp->sclass = EXTERN; + sp->sflags = sp->slevel = 0; + + return sp; +} + +int gotnr; /* tempnum for GOT register */ + +/* + * Create a reference for an extern variable. + */ +static NODE * +picext(NODE *p) +{ + NODE *q; + struct symtab *sp; + char *name; + + name = p->n_sp->soname ? p->n_sp->soname : exname(p->n_sp->sname); + + if (strncmp(name, "__builtin", 9) == 0) + return p; + +#if defined(ELFABI) + + sp = picsymtab("", name, "@got(31)"); + q = xbcon(0, sp, PTR+VOID); + q = block(UMUL, q, 0, PTR+VOID, 0, MKAP(VOID)); + +#elif defined(MACHOABI) + + char buf2[64]; + NODE *r; + char *fname; + + fname = cftnsp->soname ? cftnsp->soname : cftnsp->sname; + + if (p->n_sp->sclass == EXTDEF) { + snprintf(buf2, 64, "-L%s$pb", fname); + sp = picsymtab("", name, buf2); + } else { + snprintf(buf2, 64, "$non_lazy_ptr-L%s$pb", fname); + sp = picsymtab("L", name, buf2); + addstub(&nlplist, name); + } +#if USE_GOTNR + q = tempnode(gotnr, PTR+VOID, 0, MKAP(VOID)); +#else + q = block(REG, NIL, NIL, PTR+VOID, 0, MKAP(VOID)); + regno(q) = GOTREG; +#endif + r = xbcon(0, sp, INT); + q = buildtree(PLUS, q, r); + + if (p->n_sp->sclass != EXTDEF) + q = block(UMUL, q, 0, PTR+VOID, 0, MKAP(VOID)); + +#endif + + q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap); + q->n_sp = p->n_sp; /* for init */ + nfree(p); + + return q; +} + +/* + * Create a reference for a static variable + */ + +static NODE * +picstatic(NODE *p) +{ + NODE *q; + struct symtab *sp; + +#if defined(ELFABI) + char *n; + + if (p->n_sp->slevel > 0) { + char buf[64]; + snprintf(buf, 64, LABFMT, (int)p->n_sp->soffset); + sp = picsymtab("", buf, "@got(31)"); + } else { + n = p->n_sp->soname ? p->n_sp->soname : p->n_sp->sname; + sp = picsymtab("", exname(n), "@got(31)"); + } + sp->sclass = STATIC; + sp->stype = p->n_sp->stype; + q = xbcon(0, sp, PTR+VOID); + q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap); + q->n_sp = p->n_sp; + nfree(p); + +#elif defined(MACHOABI) + + char buf2[64]; + NODE *r; + + snprintf(buf2, 64, "-L%s$pb", + cftnsp->soname ? cftnsp->soname : cftnsp->sname); + + if (p->n_sp->slevel > 0) { + char buf1[64]; + snprintf(buf1, 64, LABFMT, (int)p->n_sp->soffset); + sp = picsymtab("", buf1, buf2); + } else { + char *name = p->n_sp->soname ? p->n_sp->soname : exname(p->n_sp->sname); + sp = picsymtab("", name, buf2); + } + sp->sclass = STATIC; + sp->stype = p->n_sp->stype; +#if USE_GOTNR + q = tempnode(gotnr, PTR+VOID, 0, MKAP(VOID)); +#else + q = block(REG, NIL, NIL, PTR+VOID, 0, MKAP(VOID)); + regno(q) = GOTREG; +#endif + r = xbcon(0, sp, INT); + q = buildtree(PLUS, q, r); + q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap); + q->n_sp = p->n_sp; + nfree(p); + +#endif + + return q; +} + +static NODE * +convert_ulltof(NODE *p) +{ + NODE *q, *r, *l, *t; + int ty; + int tmpnr; + + ty = p->n_type; + l = p->n_left; + nfree(p); + + q = tempnode(0, ULONGLONG, 0, MKAP(ULONGLONG)); + tmpnr = regno(q); + t = buildtree(ASSIGN, q, l); + ecomp(t); + +#if 0 + q = tempnode(tmpnr, ULONGLONG, 0, MKAP(ULONGLONG)); + q = block(SCONV, q, NIL, LONGLONG, 0, MKAP(LONGLONG)); +#endif + q = tempnode(tmpnr, LONGLONG, 0, MKAP(LONGLONG)); + r = block(SCONV, q, NIL, ty, 0, MKAP(ty)); + + q = tempnode(tmpnr, ULONGLONG, 0, MKAP(ULONGLONG)); + q = block(RS, q, bcon(1), ULONGLONG, 0, MKAP(ULONGLONG)); + q = block(SCONV, q, NIL, LONGLONG, 0, MKAP(LONGLONG)); + q = block(SCONV, q, NIL, ty, 0, MKAP(ty)); + t = block(FCON, NIL, NIL, ty, 0, MKAP(ty)); + t->n_dcon = 2; + l = block(MUL, q, t, ty, 0, MKAP(ty)); + + r = buildtree(COLON, l, r); + + q = tempnode(tmpnr, ULONGLONG, 0, MKAP(ULONGLONG)); + q = block(SCONV, q, NIL, LONGLONG, 0, MKAP(LONGLONG)); + l = block(LE, q, xbcon(0, NULL, LONGLONG), INT, 0, MKAP(INT)); + + return clocal(buildtree(QUEST, l, r)); + +} + + +/* clocal() is called to do local transformations on + * an expression tree preparitory to its being + * written out in intermediate code. + * + * the major essential job is rewriting the + * automatic variables and arguments in terms of + * REG and OREG nodes + * conversion ops which are not necessary are also clobbered here + * in addition, any special features (such as rewriting + * exclusive or) are easily handled here as well + */ +NODE * +clocal(NODE *p) +{ + + struct symtab *q; + NODE *r, *l; + int o; + int m; + TWORD t; + int isptrvoid = 0; + int tmpnr; + +#ifdef PCC_DEBUG + if (xdebug) { + printf("clocal: %p\n", p); + fwalk(p, eprint, 0); + } +#endif + switch (o = p->n_op) { + + case ADDROF: +#ifdef PCC_DEBUG + if (xdebug) { + printf("clocal(): ADDROF\n"); + printf("type: 0x%x\n", p->n_type); + } +#endif + /* XXX cannot takes addresses of PARAMs */ + + if (kflag == 0 || blevel == 0) + break; + /* char arrays may end up here */ + l = p->n_left; + if (l->n_op != NAME || + (l->n_type != ARY+CHAR && l->n_type != ARY+WCHAR_TYPE)) + break; + l = p; + p = picstatic(p->n_left); + nfree(l); + if (p->n_op != UMUL) + cerror("ADDROF error"); + l = p; + p = p->n_left; + nfree(l); + break; + + case NAME: + if ((q = p->n_sp) == NULL) + return p; /* Nothing to care about */ + + switch (q->sclass) { + + case PARAM: + case AUTO: + /* fake up a structure reference */ + r = block(REG, NIL, NIL, PTR+STRTY, 0, 0); + r->n_lval = 0; + r->n_rval = FPREG; + p = stref(block(STREF, r, p, 0, 0, 0)); + break; + + case USTATIC: + if (kflag == 0) + break; + /* FALLTHROUGH */ + + case STATIC: + if (kflag == 0) { + if (q->slevel == 0) + break; + p->n_lval = 0; + } else if (blevel > 0) { + p = picstatic(p); + } + break; + + case REGISTER: + p->n_op = REG; + p->n_lval = 0; + p->n_rval = q->soffset; + break; + + case EXTERN: + case EXTDEF: + if (kflag == 0) + break; + if (blevel > 0) + p = picext(p); + break; + } + break; + + case UCALL: + case CALL: + case USTCALL: + case STCALL: + if (p->n_type == VOID) + break; + /* + * if the function returns void*, ecode() invokes + * delvoid() to convert it to uchar*. + * We just let this happen on the ASSIGN to the temp, + * and cast the pointer back to void* on access + * from the temp. + */ + if (p->n_type == PTR+VOID) + isptrvoid = 1; + r = tempnode(0, p->n_type, p->n_df, p->n_ap); + tmpnr = regno(r); + r = buildtree(ASSIGN, r, p); + + p = tempnode(tmpnr, r->n_type, r->n_df, r->n_ap); + if (isptrvoid) { + p = block(PCONV, p, NIL, PTR+VOID, + p->n_df, MKAP(PTR+VOID)); + } +#if 1 + p = buildtree(COMOP, r, p); +#else + /* XXX this doesn't work if the call is already in a COMOP */ + r = clocal(r); + ecomp(r); +#endif + break; + + case CBRANCH: + l = p->n_left; + + /* + * Remove unnecessary conversion ops. + */ + if (clogop(l->n_op) && l->n_left->n_op == SCONV) { + if (coptype(l->n_op) != BITYPE) + break; + if (l->n_right->n_op == ICON) { + r = l->n_left->n_left; + if (r->n_type >= FLOAT && r->n_type <= LDOUBLE) + break; + /* Type must be correct */ + t = r->n_type; + nfree(l->n_left); + l->n_left = r; + l->n_type = t; + l->n_right->n_type = t; + } + } + break; + + case PCONV: + /* Remove redundant PCONV's. Be careful */ + l = p->n_left; + if (l->n_op == ICON) { + l->n_lval = (unsigned)l->n_lval; + goto delp; + } + if (l->n_type < INT || DEUNSIGN(l->n_type) == LONGLONG) { + /* float etc? */ + p->n_left = block(SCONV, l, NIL, + UNSIGNED, 0, MKAP(UNSIGNED)); + break; + } + /* if left is SCONV, cannot remove */ + if (l->n_op == SCONV) + break; + + /* avoid ADDROF TEMP */ + if (l->n_op == ADDROF && l->n_left->n_op == TEMP) + break; + + /* if conversion to another pointer type, just remove */ + if (p->n_type > BTMASK && l->n_type > BTMASK) + goto delp; + break; + + delp: l->n_type = p->n_type; + l->n_qual = p->n_qual; + l->n_df = p->n_df; + l->n_ap = p->n_ap; + nfree(p); + p = l; + break; + + case SCONV: + l = p->n_left; + + if (p->n_type == l->n_type) { + nfree(p); + return l; + } + + if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 && + btattr[p->n_type].atypsz == btattr[l->n_type].atypsz) { + if (p->n_type != FLOAT && p->n_type != DOUBLE && + l->n_type != FLOAT && l->n_type != DOUBLE && + l->n_type != LDOUBLE && p->n_type != LDOUBLE) { + if (l->n_op == NAME || l->n_op == UMUL || + l->n_op == TEMP) { + l->n_type = p->n_type; + nfree(p); + return l; + } + } + } + + if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT && + coptype(l->n_op) == BITYPE) { + l->n_type = p->n_type; + nfree(p); + return l; + } + + /* + * if converting ULONGLONG to FLOAT/(L)DOUBLE, + * replace ___floatunsdidf() with ___floatdidf() + */ + if (l->n_type == ULONGLONG && p->n_type >= FLOAT && + p->n_type <= LDOUBLE) { + return convert_ulltof(p); + } + + o = l->n_op; + m = p->n_type; + + if (o == ICON) { + CONSZ val = l->n_lval; + + if (!ISPTR(m)) /* Pointers don't need to be conv'd */ + switch (m) { + case BOOL: + l->n_lval = l->n_lval != 0; + break; + case CHAR: + l->n_lval = (char)val; + break; + case UCHAR: + l->n_lval = val & 0377; + break; + case SHORT: + l->n_lval = (short)val; + break; + case USHORT: + l->n_lval = val & 0177777; + break; + case ULONG: + case UNSIGNED: + l->n_lval = val & 0xffffffff; + break; + case LONG: + case INT: + l->n_lval = (int)val; + break; + case LONGLONG: + l->n_lval = (long long)val; + break; + case ULONGLONG: + l->n_lval = val; + break; + case VOID: + break; + case LDOUBLE: + case DOUBLE: + case FLOAT: + l->n_op = FCON; + l->n_dcon = val; + break; + default: + cerror("unknown type %d", m); + } + l->n_type = m; + l->n_ap = MKAP(m); + nfree(p); + return l; + } else if (o == FCON) { + l->n_lval = l->n_dcon; + l->n_sp = NULL; + l->n_op = ICON; + l->n_type = m; + l->n_ap = MKAP(m); + nfree(p); + return clocal(l); + } + if (DEUNSIGN(p->n_type) == SHORT && + DEUNSIGN(l->n_type) == SHORT) { + nfree(p); + p = l; + } + if ((DEUNSIGN(p->n_type) == CHAR || + DEUNSIGN(p->n_type) == SHORT) && + (l->n_type == FLOAT || l->n_type == DOUBLE || + l->n_type == LDOUBLE)) { + p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_ap); + p->n_left->n_type = INT; + return p; + } + if ((DEUNSIGN(l->n_type) == CHAR || + DEUNSIGN(l->n_type) == SHORT) && + (p->n_type == FLOAT || p->n_type == DOUBLE || + p->n_type == LDOUBLE)) { + p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_ap); + p->n_left->n_type = INT; + return p; + } + break; + + case MOD: + simmod(p); + break; + + case DIV: + if (o == DIV && p->n_type != CHAR && p->n_type != SHORT) + break; + /* make it an int division by inserting conversions */ + p->n_left = block(SCONV, p->n_left, NIL, INT, 0, MKAP(INT)); + p->n_right = block(SCONV, p->n_right, NIL, INT, 0, MKAP(INT)); + p = block(SCONV, p, NIL, p->n_type, 0, MKAP(p->n_type)); + p->n_left->n_type = INT; + break; + + case PMCONV: + case PVCONV: + + nfree(p); + return(buildtree(o==PMCONV?MUL:DIV, p->n_left, p->n_right)); + + case STNAME: + if ((q = p->n_sp) == NULL) + return p; + if (q->sclass != STNAME) + return p; + t = p->n_type; + p = block(ADDROF, p, NIL, INCREF(t), p->n_df, p->n_ap); + p = block(UMUL, p, NIL, t, p->n_df, p->n_ap); + break; + + case FORCE: + /* put return value in return reg */ + p->n_op = ASSIGN; + p->n_right = p->n_left; + p->n_left = block(REG, NIL, NIL, p->n_type, 0, MKAP(INT)); + p->n_left->n_rval = p->n_left->n_type == BOOL ? + RETREG(BOOL_TYPE) : RETREG(p->n_type); + break; + + case LS: + case RS: + if (p->n_right->n_op == ICON) + break; /* do not do anything */ + if (DEUNSIGN(p->n_right->n_type) == INT) + break; + p->n_right = block(SCONV, p->n_right, NIL, INT, 0, MKAP(INT)); + break; + } + +#ifdef PCC_DEBUG + if (xdebug) { + printf("clocal end: %p\n", p); + fwalk(p, eprint, 0); + } +#endif + return(p); +} + +/* + * Change CALL references to either direct (static) or PLT. + */ +static void +fixnames(NODE *p, void *arg) +{ + struct symtab *sp; + struct attr *ap; + NODE *q; + char *c; + int isu; + + if ((cdope(p->n_op) & CALLFLG) == 0) + return; + + isu = 0; + q = p->n_left; + ap = q->n_ap; + if (q->n_op == UMUL) + q = q->n_left, isu = 1; + +#if defined(ELFABI) + + if (q->n_op == ICON) { + sp = q->n_sp; + +#elif defined(MACHOABI) + +#ifdef USE_GOTNR + if (q->n_op == PLUS && q->n_left->n_op == TEMP && +#else + if (q->n_op == PLUS && q->n_left->n_op == REG && +#endif + q->n_right->n_op == ICON) { + sp = q->n_right->n_sp; +#endif + + if (sp == NULL) + return; /* nothing to do */ + if (sp->sclass == STATIC && !ISFTN(sp->stype)) + return; /* function pointer */ + + if (sp->sclass != STATIC && sp->sclass != EXTERN && + sp->sclass != EXTDEF) + cerror("fixnames"); + c = NULL; +#if defined(ELFABI) + + if (sp->soname == NULL || + (c = strstr(sp->soname, "@got(31)")) == NULL) + cerror("fixnames2"); + if (isu) { + strcpy(c, "@plt"); + } else + *c = 0; + +#elif defined(MACHOABI) + + if (sp->soname == NULL || + ((c = strstr(sp->soname, "$non_lazy_ptr")) == NULL && + (c = strstr(sp->soname, "-L")) == NULL)) + cerror("fixnames2"); + if (isu) { + *c = 0; + addstub(&stublist, sp->soname+1); + strcpy(c, "$stub"); + } else + *c = 0; + + nfree(q->n_left); + q = q->n_right; + if (isu) + nfree(p->n_left->n_left); + nfree(p->n_left); + p->n_left = q; + q->n_ap = ap; + +#endif + } +} + +void +myp2tree(NODE *p) +{ + int o = p->n_op; + struct symtab *sp; + + if (kflag) + walkf(p, fixnames, 0); + if (o != FCON) + return; + + /* Write float constants to memory */ + /* Should be voluntary per architecture */ + + sp = IALLOC(sizeof(struct symtab)); + sp->sclass = STATIC; + sp->sap = MKAP(p->n_type); + sp->slevel = 1; /* fake numeric label */ + sp->soffset = getlab(); + sp->sflags = 0; + sp->stype = p->n_type; + sp->squal = (CON >> TSHIFT); + + defloc(sp); + ninval(0, tsize(sp->stype, sp->sdf, sp->sap), p); + + p->n_op = NAME; + p->n_lval = 0; + p->n_sp = sp; +} + +/*ARGSUSED*/ +int +andable(NODE *p) +{ + return(1); /* all names can have & taken on them */ +} + +/* + * at the end of the arguments of a ftn, set the automatic offset + */ +void +cendarg() +{ +#ifdef PCC_DEBUG + if (xdebug) + printf("cendarg: autooff=%d (was %d)\n", AUTOINIT, autooff); +#endif + autooff = AUTOINIT; +} + +/* + * Return 1 if a variable of type type is OK to put in register. + */ +int +cisreg(TWORD t) +{ + return 1; +} + +/* + * return a node, for structure references, which is suitable for + * being added to a pointer of type t, in order to be off bits offset + * into a structure + * t, d, and s are the type, dimension offset, and sizeoffset + * Be careful about only handling first-level pointers, the following + * indirections must be fullword. + */ +NODE * +offcon(OFFSZ off, TWORD t, union dimfun *d, struct attr *ap) +{ + register NODE *p; + +#ifdef PCC_DEBUG + if (xdebug) + printf("offcon: OFFSZ %lld type %x dim %p siz %d\n", + off, t, d, (int)tsize(t, d, ap)); +#endif + + p = bcon(0); + p->n_lval = off/SZCHAR; /* Default */ + return(p); +} + +/* + * Allocate bits on the stack. + * 'off' is the number of bits to allocate + * 'p' is a tree that when evaluated is the multiply count for 'off' + * 't' is a storeable node where to write the allocated address + */ +void +spalloc(NODE *t, NODE *p, OFFSZ off) +{ + NODE *q, *r; + int nbytes = off / SZCHAR; + int stacksize = 24+40; /* this should be p2stacksize */ + + /* + * After we subtract the requisite bytes + * off the stack, we need to step back over + * the 40 bytes for the arguments registers + * *and* any other parameters which will get + * saved to the stack. Unfortunately, we + * don't have that information in pass1 and + * the parameters will stomp on the allocated + * space for alloca(). + * + * No fix yet. + */ + werror("parameters may stomp on alloca()"); + + /* compute size */ + p = buildtree(MUL, p, bcon(nbytes)); + p = buildtree(PLUS, p, bcon(ALSTACK/SZCHAR)); + + /* load the top-of-stack */ + q = block(REG, NIL, NIL, PTR+INT, 0, MKAP(INT)); + regno(q) = SPREG; + q = block(UMUL, q, NIL, INT, 0, MKAP(INT)); + + /* save old top-of-stack value to new top-of-stack position */ + r = block(REG, NIL, NIL, PTR+INT, 0, MKAP(INT)); + regno(r) = SPREG; + r = block(MINUSEQ, r, p, INT, 0, MKAP(INT)); + r = block(UMUL, r, NIL, INT, 0, MKAP(INT)); + ecomp(buildtree(ASSIGN, r, q)); + + r = block(REG, NIL, NIL, PTR+INT, 0, MKAP(INT)); + regno(r) = SPREG; + + /* skip over the arguments space and align to 16 bytes */ + r = block(PLUS, r, bcon(stacksize + 15), INT, 0, MKAP(INT)); + r = block(RS, r, bcon(4), INT, 0, MKAP(INT)); + r = block(LS, r, bcon(4), INT, 0, MKAP(INT)); + + t->n_type = p->n_type; + ecomp(buildtree(ASSIGN, t, r)); +} + +/* + * Print out a string of characters. + * Unfortunately, this code assumes that the assembler understands + * C-style escape sequences. (which it doesn't!) + * Location is already set. + */ +void +instring(struct symtab *sp) +{ + char *s, *str = sp->sname; + +#if defined(ELFABI) + + defloc(sp); + +#elif defined(MACHOABI) + + extern int lastloc; + if (lastloc != STRNG) + printf(" .cstring\n"); + lastloc = STRNG; + printf("\t.p2align 2\n"); + printf(LABFMT ":\n", sp->soffset); + +#endif + + /* be kind to assemblers and avoid long strings */ + printf("\t.ascii \""); + for (s = str; *s != 0; ) { + if (*s++ == '\\') { + (void)esccon(&s); + } + if (s - str > 64) { + fwrite(str, 1, s - str, stdout); + printf("\"\n\t.ascii \""); + str = s; + } + } + fwrite(str, 1, s - str, stdout); + printf("\\0\"\n"); +} + +static int inbits, inval; + +/* + * set fsz bits in sequence to zero. + */ +void +zbits(OFFSZ off, int fsz) +{ + int m; + + if (idebug) + printf("zbits off %lld, fsz %d inbits %d\n", off, fsz, inbits); + +#if 0 + /* little-endian */ + if ((m = (inbits % SZCHAR))) { + m = SZCHAR - m; + if (fsz < m) { + inbits += fsz; + return; + } else { + fsz -= m; + printf("\t.byte %d\n", inval); + inval = inbits = 0; + } + } +#endif + /* big-endian */ + if (inbits) { + m = SZCHAR - inbits; + if (fsz < m) { + inbits += fsz; + inval <<= fsz; + } else { + printf("\t.byte %d\n", inval << m); + fsz -= m; + inval = inbits = 0; + } + } + + if (fsz >= SZCHAR) { + printf("\t.space %d\n", fsz/SZCHAR); + fsz -= (fsz/SZCHAR) * SZCHAR; + } + if (fsz) { + inval = 0; + inbits = fsz; + } +} + +/* + * Initialize a bitfield. + */ +void +infld(CONSZ off, int fsz, CONSZ val) +{ + if (idebug) + printf("infld off %lld, fsz %d, val %lld inbits %d\n", + off, fsz, val, inbits); + + val &= (1 << fsz)-1; + +#if 0 + /* little-endian */ + while (fsz + inbits >= SZCHAR) { + inval |= (val << inbits); + printf("\t.byte %d\n", inval & 255); + fsz -= (SZCHAR - inbits); + val >>= (SZCHAR - inbits); + inval = inbits = 0; + } + if (fsz) { + inval |= (val << inbits); + inbits += fsz; + } +#endif + + /* big-endian */ + inval <<= fsz; + inval |= val; + inbits += fsz; + while (inbits >= SZCHAR) { + int pval = inval >> (inbits - SZCHAR); + printf("\t.byte %d\n", pval & 255); + inbits -= SZCHAR; + } +} + +/* + * print out a constant node, may be associated with a label. + * Do not free the node after use. + * off is bit offset from the beginning of the aggregate + * fsz is the number of bits this is referring to + */ +void +ninval(CONSZ off, int fsz, NODE *p) +{ + union { float f; double d; long double l; int i[3]; } u; + struct symtab *q; + char *c; + TWORD t; + int i; + + t = p->n_type; + if (t > BTMASK) + t = INT; /* pointer */ + + while (p->n_op == SCONV || p->n_op == PCONV) { + NODE *l = p->n_left; + l->n_type = p->n_type; + p = l; + } + + if (kflag && (p->n_op == PLUS || p->n_op == UMUL)) { + if (p->n_op == UMUL) + p = p->n_left; + p = p->n_right; + q = p->n_sp; + +#if defined(ELFABI) + + if (q->soname && (c = strstr(q->soname, "@got(31)")) != NULL) + *c = 0; /* ignore GOT ref here */ + +#elif defined(MACHOABI) + + if ((c = strstr(q->soname, "$non_lazy_ptr")) != NULL) { + q->soname++; /* skip "L" */ + *c = 0; /* ignore GOT ref here */ + } + else if ((c = strstr(q->soname, "-L")) != NULL) + *c = 0; /* ignore GOT ref here */ + +#endif + + } + + if (p->n_op != ICON && p->n_op != FCON) + cerror("ninval: init node not constant: node %p [%s]", + p, cftnsp->soname); + + if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT) + uerror("element not constant"); + + switch (t) { + case LONGLONG: + case ULONGLONG: +#if 0 + /* little-endian */ + i = (p->n_lval >> 32); + p->n_lval &= 0xffffffff; + p->n_type = INT; + ninval(off, 32, p); + p->n_lval = i; + ninval(off+32, 32, p); +#endif + /* big-endian */ + i = (p->n_lval & 0xffffffff); + p->n_lval >>= 32; + p->n_type = INT; + ninval(off, 32, p); + p->n_lval = i; + ninval(off+32, 32, p); + + break; + case INT: + case UNSIGNED: + printf("\t.long %d", (int)p->n_lval); + if ((q = p->n_sp) != NULL) { + if ((q->sclass == STATIC && q->slevel > 0)) { + printf("+" LABFMT, q->soffset); + } else { + char *name = q->soname ? q->soname : exname(q->sname); + printf("+%s", name); + } + } + printf("\n"); + break; + case SHORT: + case USHORT: + printf("\t.short %d\n", (int)p->n_lval & 0xffff); + break; + case BOOL: + if (p->n_lval > 1) + p->n_lval = p->n_lval != 0; + /* FALLTHROUGH */ + case CHAR: + case UCHAR: + printf("\t.byte %d\n", (int)p->n_lval & 0xff); + break; + case LDOUBLE: + u.i[2] = 0; + u.l = (long double)p->n_dcon; +#if 0 + /* little-endian */ + printf("\t.long 0x%x,0x%x,0x%x\n", u.i[0], u.i[1], u.i[2]); +#endif + /* big-endian */ + printf("\t.long 0x%x,0x%x,0x%x\n", u.i[0], u.i[1], u.i[2]); + break; + case DOUBLE: + u.d = (double)p->n_dcon; + printf("\t.long 0x%x\n\t.long 0x%x\n", u.i[0], u.i[1]); + break; + case FLOAT: + u.f = (float)p->n_dcon; + printf("\t.long 0x%x\n", u.i[0]); + break; + default: + cerror("ninval"); + } +} + +/* make a name look like an external name in the local machine */ +char * +exname(char *p) +{ +#if defined(ELFABI) + + return (p == NULL ? "" : p); + +#elif defined(MACHOABI) + +#define NCHNAM 256 + static char text[NCHNAM+1]; + int i; + + if (p == NULL) + return ""; + + text[0] = '_'; + for (i=1; *p && istype, sp->sdf, sp->sap); + off = (off+(SZCHAR-1))/SZCHAR; + printf("\t.%scomm ", sp->sclass == STATIC ? "l" : ""); + n = sp->soname ? sp->soname : exname(sp->sname); + if (sp->slevel == 0) + printf("%s,%d\n", n, off); + else + printf(LABFMT ",%d\n", sp->soffset, off); +} + + +#ifdef notdef +/* make a common declaration for id, if reasonable */ +void +commdec(struct symtab *q) +{ + int off; + + off = tsize(q->stype, q->sdf, q->ssue); + off = (off+(SZCHAR-1))/SZCHAR; + printf("\t.comm %s,0%o\n", q->soname ? q->soname : exname(q->sname), off); +} + +/* make a local common declaration for id, if reasonable */ +void +lcommdec(struct symtab *q) +{ + int off; + + off = tsize(q->stype, q->sdf, q->ssue); + off = (off+(SZCHAR-1))/SZCHAR; + if (q->slevel == 0) + printf("\t.lcomm %s,%d\n", q->soname ? q->soname : exname(q->sname), off); + else + printf("\t.lcomm " LABFMT ",%d\n", q->soffset, off); +} + +/* + * print a (non-prog) label. + */ +void +deflab1(int label) +{ + printf(LABFMT ":\n", label); +} + +#if defined(ELFABI) + +static char *loctbl[] = { "text", "data", "section .rodata,", + "section .rodata" }; + +#elif defined(MACHOABI) + +static char *loctbl[] = { "text", "data", "section .rodata,", "cstring" }; + +#endif + +void +setloc1(int locc) +{ +#ifdef PCC_DEBUG + if (xdebug) + printf("setloc1: locc=%d, lastloc=%d\n", locc, lastloc); +#endif + + if (locc == lastloc) + return; + lastloc = locc; + printf(" .%s\n", loctbl[locc]); +} +#endif + +/* simulate and optimise the MOD opcode */ +static void +simmod(NODE *p) +{ + NODE *r = p->n_right; + + assert(p->n_op == MOD); + + if (!ISUNSIGNED(p->n_type)) + return; + +#define ISPOW2(n) ((n) && (((n)&((n)-1)) == 0)) + + /* if the right is a constant power of two, then replace with AND */ + if (r->n_op == ICON && ISPOW2(r->n_lval)) { + p->n_op = AND; + r->n_lval--; + return; + } + +#undef ISPOW2 + + /* other optimizations can go here */ +} + +static int constructor; +static int destructor; + +/* + * Give target the opportunity of handling pragmas. + */ +int +mypragma(char *str) +{ + if (strcmp(str, "tls") == 0) { + uerror("thread-local storage not supported for this target"); + return 1; + } + if (strcmp(str, "constructor") == 0 || strcmp(str, "init") == 0) { + constructor = 1; + return 1; + } + if (strcmp(str, "destructor") == 0 || strcmp(str, "fini") == 0) { + destructor = 1; + return 1; + } + + return 0; +} + +/* + * Called when a identifier has been declared, to give target last word. + */ +void +fixdef(struct symtab *sp) +{ + /* may have sanity checks here */ + if ((constructor || destructor) && (sp->sclass != PARAM)) { +#ifdef MACHOABI + if (kflag) { + if (constructor) + printf("\t.mod_init_func\n"); + else + printf("\t.mod_term_func\n"); + } else { + if (constructor) + printf("\t.constructor\n"); + else + printf("\t.destructor\n"); + } + printf("\t.p2align 2\n"); + printf("\t.long %s\n", exname(sp->sname)); + printf("\t.text\n"); + constructor = destructor = 0; +#endif + } +} + +/* + * There is very little different here to the standard builtins. + * It basically handles promotion of types smaller than INT. + */ + +NODE * +powerpc_builtin_stdarg_start(NODE *f, NODE *a, TWORD t) +{ + NODE *p, *q; + int sz = 1; + + /* check num args and type */ + if (a == NULL || a->n_op != CM || a->n_left->n_op == CM || + !ISPTR(a->n_left->n_type)) + goto bad; + + /* must first deal with argument size; use int size */ + p = a->n_right; + if (p->n_type < INT) { + /* round up to word */ + sz = SZINT / tsize(p->n_type, p->n_df, p->n_ap); + } + + p = buildtree(ADDROF, p, NIL); /* address of last arg */ + p = optim(buildtree(PLUS, p, bcon(sz))); + q = block(NAME, NIL, NIL, PTR+VOID, 0, 0); + q = buildtree(CAST, q, p); + p = q->n_right; + nfree(q->n_left); + nfree(q); + p = buildtree(ASSIGN, a->n_left, p); + tfree(f); + nfree(a); + + return p; + +bad: + uerror("bad argument to __builtin_stdarg_start"); + return bcon(0); +} + +NODE * +powerpc_builtin_va_arg(NODE *f, NODE *a, TWORD t) +{ + NODE *p, *q, *r; + int sz, tmpnr; + + /* check num args and type */ + if (a == NULL || a->n_op != CM || a->n_left->n_op == CM || + !ISPTR(a->n_left->n_type) || a->n_right->n_op != TYPE) + goto bad; + + r = a->n_right; + + /* get type size */ + sz = tsize(r->n_type, r->n_df, r->n_ap) / SZCHAR; + if (sz < SZINT/SZCHAR) { + werror("%s%s promoted to int when passed through ...", + ISUNSIGNED(r->n_type) ? "unsigned " : "", + DEUNSIGN(r->n_type) == SHORT ? "short" : "char"); + sz = SZINT/SZCHAR; + r->n_type = INT; + r->n_ap = MKAP(INT); + } + + p = tcopy(a->n_left); + +#if defined(ELFABI) + + /* alignment */ + if (SZINT/SZCHAR && r->n_type != UNIONTY && r->n_type != STRTY) { + p = buildtree(PLUS, p, bcon(ALSTACK/8 - 1)); + p = block(AND, p, bcon(-ALSTACK/8), p->n_type, p->n_df, p->n_ap); + } + +#endif + + /* create a copy to a temp node */ + q = tempnode(0, p->n_type, p->n_df, p->n_ap); + tmpnr = regno(q); + p = buildtree(ASSIGN, q, p); + + q = tempnode(tmpnr, p->n_type, p->n_df, p->n_ap); + q = buildtree(PLUS, q, bcon(sz)); + q = buildtree(ASSIGN, a->n_left, q); + + q = buildtree(COMOP, p, q); + + nfree(a->n_right); + nfree(a); + nfree(f); + + p = tempnode(tmpnr, INCREF(r->n_type), r->n_df, r->n_ap); + p = buildtree(UMUL, p, NIL); + p = buildtree(COMOP, q, p); + + return p; + +bad: + uerror("bad argument to __builtin_va_arg"); + return bcon(0); +} + +NODE * +powerpc_builtin_va_end(NODE *f, NODE *a, TWORD t) +{ + tfree(f); + tfree(a); + + return bcon(0); +} + +NODE * +powerpc_builtin_va_copy(NODE *f, NODE *a, TWORD t) +{ + if (a == NULL || a->n_op != CM || a->n_left->n_op == CM) + goto bad; + tfree(f); + f = buildtree(ASSIGN, a->n_left, a->n_right); + nfree(a); + return f; + +bad: + uerror("bad argument to __buildtin_va_copy"); + return bcon(0); +} + +NODE * +powerpc_builtin_return_address(NODE *f, NODE *a, TWORD t) +{ + int nframes; + int i = 0; + + if (a == NULL || a->n_op != ICON) + goto bad; + + nframes = a->n_lval; + + tfree(f); + tfree(a); + + f = block(REG, NIL, NIL, PTR+VOID, 0, MKAP(VOID)); + regno(f) = SPREG; + + do { + f = block(UMUL, f, NIL, PTR+VOID, 0, MKAP(VOID)); + } while (i++ < nframes); + + f = block(PLUS, f, bcon(8), INCREF(PTR+VOID), 0, MKAP(VOID)); + f = buildtree(UMUL, f, NIL); + + return f; +bad: + uerror("bad argument to __builtin_return_address"); + return bcon(0); +} + +NODE * +powerpc_builtin_frame_address(NODE *f, NODE *a, TWORD t) +{ + int nframes; + int i = 0; + + if (a == NULL || a->n_op != ICON) + goto bad; + + nframes = a->n_lval; + + tfree(f); + tfree(a); + + if (nframes == 0) { + f = block(REG, NIL, NIL, PTR+VOID, 0, MKAP(VOID)); + regno(f) = FPREG; + } else { + f = block(REG, NIL, NIL, PTR+VOID, 0, MKAP(VOID)); + regno(f) = SPREG; + do { + f = block(UMUL, f, NIL, PTR+VOID, 0, MKAP(VOID)); + } while (i++ < nframes); + f = block(PLUS, f, bcon(24), INCREF(PTR+VOID), 0, MKAP(VOID)); + f = buildtree(UMUL, f, NIL); + } + + return f; +bad: + uerror("bad argument to __builtin_frame_address"); + return bcon(0); +} + +void +pass1_lastchance(struct interpass *ip) +{ +} diff --git a/compilers/pcc/pcc-1.0.0/arch/powerpc/local2.c b/compilers/pcc/pcc-1.0.0/arch/powerpc/local2.c new file mode 100644 index 00000000..e768ad25 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/powerpc/local2.c @@ -0,0 +1,1517 @@ +/* $Id: local2.c,v 1.25 2010/11/26 17:06:31 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "pass1.h" /* for cftnsp */ +#include "pass2.h" +#include +#include +#include + +#if defined(MACHOABI) +#define EXPREFIX "_" +#else +#define EXPREFIX "" +#endif + +#define LOWREG 0 +#define HIREG 1 + +char *rnames[] = { + REGPREFIX "r0", REGPREFIX "r1", + REGPREFIX "r2", REGPREFIX "r3", + REGPREFIX "r4", REGPREFIX "r5", + REGPREFIX "r6", REGPREFIX "r7", + REGPREFIX "r8", REGPREFIX "r9", + REGPREFIX "r10", REGPREFIX "r11", + REGPREFIX "r12", REGPREFIX "r13", + REGPREFIX "r14", REGPREFIX "r15", + REGPREFIX "r16", REGPREFIX "r17", + REGPREFIX "r18", REGPREFIX "r19", + REGPREFIX "r20", REGPREFIX "r21", + REGPREFIX "r22", REGPREFIX "r23", + REGPREFIX "r24", REGPREFIX "r25", + REGPREFIX "r26", REGPREFIX "r27", + REGPREFIX "r28", REGPREFIX "r29", + REGPREFIX "r30", REGPREFIX "r31", + "r4\0r3\0", "r5\0r4\0", "r6\0r5\0", "r7\0r6\0", + "r8\0r7\0", "r9\0r8\0", "r10r9\0", "r15r14", "r17r16", + "r19r18", "r21r20", "r23r22", "r25r24", "r27r26", + "r29r28", "r31r30", + REGPREFIX "f0", REGPREFIX "f1", + REGPREFIX "f2", REGPREFIX "f3", + REGPREFIX "f4", REGPREFIX "f5", + REGPREFIX "f6", REGPREFIX "f7", + REGPREFIX "f8", REGPREFIX "f9", + REGPREFIX "f10", REGPREFIX "f11", + REGPREFIX "f12", REGPREFIX "f13", + REGPREFIX "f14", REGPREFIX "f15", + REGPREFIX "f16", REGPREFIX "f17", + REGPREFIX "f18", REGPREFIX "f19", + REGPREFIX "f20", REGPREFIX "f21", + REGPREFIX "f22", REGPREFIX "f23", + REGPREFIX "f24", REGPREFIX "f25", + REGPREFIX "f26", REGPREFIX "f27", + REGPREFIX "f28", REGPREFIX "f29", + REGPREFIX "f30", REGPREFIX "f31", +}; + +static int argsize(NODE *p); + +static int p2calls; +static int p2temps; /* TEMPs which aren't autos yet */ +static int p2framesize; +static int p2maxstacksize; + +void +deflab(int label) +{ + printf(LABFMT ":\n", label); +} + +static TWORD ftype; + +/* + * Print out the prolog assembler. + */ +void +prologue(struct interpass_prolog *ipp) +{ + int addto; + +#ifdef PCC_DEBUG + if (x2debug) + printf("prologue: type=%d, lineno=%d, name=%s, vis=%d, ipptype=%d, regs=0x%lx, autos=%d, tmpnum=%d, lblnum=%d\n", + ipp->ipp_ip.type, + ipp->ipp_ip.lineno, + ipp->ipp_name, + ipp->ipp_vis, + ipp->ipp_type, + ipp->ipp_regs[0], + ipp->ipp_autos, + ipp->ip_tmpnum, + ipp->ip_lblnum); +#endif + + ftype = ipp->ipp_type; + + addto = p2framesize; + + if (p2calls != 0 || kflag) { + /* get return address (not required for leaf function) */ + printf("\tmflr %s\n", rnames[R0]); + printf("\tstw %s,8(%s)\n", rnames[R0], rnames[R1]); + } + /* save registers R30 and R31 */ + printf("\tstmw %s,-8(%s)\n", rnames[R30], rnames[R1]); +#ifdef FPREG + printf("\tmr %s,%s\n", rnames[FPREG], rnames[R1]); +#endif + /* create the new stack frame */ + if (addto > 32767) { + printf("\tlis %s,%d\n", rnames[R0], (-addto) >> 16); + printf("\tori %s,%s,%d\n", rnames[R0], + rnames[R0], (-addto) & 0xffff); + printf("\tstwux %s,%s,%s\n", rnames[R1], + rnames[R1], rnames[R0]); + } else { + printf("\tstwu %s,-%d(%s)\n", rnames[R1], addto, rnames[R1]); + } + + if (kflag) { +#if defined(ELFABI) + printf("\tbl _GLOBAL_OFFSET_TABLE_@local-4\n"); + printf("\tmflr %s\n", rnames[GOTREG]); +#elif defined(MACHOABI) + printf("\tbcl 20,31,L%s$pb\n", ipp->ipp_name + 1); + printf("L%s$pb:\n", ipp->ipp_name + 1); + printf("\tmflr %s\n", rnames[GOTREG]); +#endif + } + +} + + +void +eoftn(struct interpass_prolog *ipp) +{ + +#ifdef PCC_DEBUG + if (x2debug) + printf("eoftn:\n"); +#endif + + if (ipp->ipp_ip.ip_lbl == 0) + return; /* no code needs to be generated */ + + /* struct return needs special treatment */ + if (ftype == STRTY || ftype == UNIONTY) + cerror("eoftn"); + + /* unwind stack frame */ + printf("\tlwz %s,0(%s)\n", rnames[R1], rnames[R1]); + if (p2calls != 0 || kflag) { + printf("\tlwz %s,8(%s)\n", rnames[R0], rnames[R1]); + printf("\tmtlr %s\n", rnames[R0]); + } + printf("\tlmw %s,-8(%s)\n", rnames[R30], rnames[R1]); + printf("\tblr\n"); +} + +/* + * add/sub/... + * + * Param given: + */ +void +hopcode(int f, int o) +{ + char *str; + + switch (o) { + case PLUS: + str = "addw"; + break; + case MINUS: + str = "subw"; + break; + case AND: + str = "and"; + break; + case OR: + str = "or"; + break; + case ER: + str = "xor"; + break; + default: + comperr("hopcode2: %d", o); + str = 0; /* XXX gcc */ + } + printf("%s%c", str, f); +} + +/* + * Return type size in bytes. Used by R2REGS, arg 2 to offset(). + */ +int +tlen(NODE *p) +{ + switch(p->n_type) { + case CHAR: + case UCHAR: + return(1); + + case SHORT: + case USHORT: + return(SZSHORT/SZCHAR); + + case DOUBLE: + return(SZDOUBLE/SZCHAR); + + case INT: + case UNSIGNED: + case LONG: + case ULONG: + return(SZINT/SZCHAR); + + case LONGLONG: + case ULONGLONG: + return SZLONGLONG/SZCHAR; + + default: + if (!ISPTR(p->n_type)) + comperr("tlen type %d not pointer"); + return SZPOINT(p->n_type)/SZCHAR; + } +} + +/* + * Emit code to compare two longlong numbers. + */ +static void +twollcomp(NODE *p) +{ + int o = p->n_op; + int s = getlab2(); + int e = p->n_label; + int cb1, cb2; + + if (o >= ULE) + o -= (ULE-LE); + switch (o) { + case NE: + cb1 = 0; + cb2 = NE; + break; + case EQ: + cb1 = NE; + cb2 = 0; + break; + case LE: + case LT: + cb1 = GT; + cb2 = LT; + break; + case GE: + case GT: + cb1 = LT; + cb2 = GT; + break; + + default: + cb1 = cb2 = 0; /* XXX gcc */ + } + if (p->n_op >= ULE) + cb1 += 4, cb2 += 4; + if (p->n_op >= ULE) + expand(p, 0, "\tcmplw UL,UR" COM "compare 64-bit values (upper)\n"); + else + expand(p, 0, "\tcmpw UL,UR" COM "compare 64-bit values (upper)\n"); + if (cb1) cbgen(cb1, s); + if (cb2) cbgen(cb2, e); + if (p->n_op >= ULE) + expand(p, 0, "\tcmplw AL,AR" COM "(and lower)\n"); + else + expand(p, 0, "\tcmpw AL,AR" COM "(and lower)\n"); + cbgen(p->n_op, e); + deflab(s); +} + +static void +shiftop(NODE *p) +{ + NODE *r = p->n_right; + TWORD ty = p->n_type; + + if (p->n_op == LS && r->n_op == ICON && r->n_lval < 32) { + expand(p, INBREG, "\tsrwi A1,AL,32-AR" COM "64-bit left-shift\n"); + expand(p, INBREG, "\tslwi U1,UL,AR\n"); + expand(p, INBREG, "\tor U1,U1,A1\n"); + expand(p, INBREG, "\tslwi A1,AL,AR\n"); + } else if (p->n_op == LS && r->n_op == ICON && r->n_lval < 64) { + expand(p, INBREG, "\tli A1,0" COM "64-bit left-shift\n"); + if (r->n_lval == 32) + expand(p, INBREG, "\tmr U1,AL\n"); + else + expand(p, INBREG, "\tslwi U1,AL,AR-32\n"); + } else if (p->n_op == LS && r->n_op == ICON) { + expand(p, INBREG, "\tli A1,0" COM "64-bit left-shift\n"); + expand(p, INBREG, "\tli U1,0\n"); + } else if (p->n_op == RS && r->n_op == ICON && r->n_lval < 32) { + expand(p, INBREG, "\tslwi U1,UL,32-AR" COM "64-bit right-shift\n"); + expand(p, INBREG, "\tsrwi A1,AL,AR\n"); + expand(p, INBREG, "\tor A1,A1,U1\n"); + if (ty == LONGLONG) + expand(p, INBREG, "\tsrawi U1,UL,AR\n"); + else + expand(p, INBREG, "\tsrwi U1,UL,AR\n"); + } else if (p->n_op == RS && r->n_op == ICON && r->n_lval < 64) { + if (ty == LONGLONG) + expand(p, INBREG, "\tli U1,-1" COM "64-bit right-shift\n"); + else + expand(p, INBREG, "\tli U1,0" COM "64-bit right-shift\n"); + if (r->n_lval == 32) + expand(p, INBREG, "\tmr A1,UL\n"); + else if (ty == LONGLONG) + expand(p, INBREG, "\tsrawi A1,UL,AR-32\n"); + else + expand(p, INBREG, "\tsrwi A1,UL,AR-32\n"); + } else if (p->n_op == RS && r->n_op == ICON) { + expand(p, INBREG, "\tli A1,0" COM "64-bit right-shift\n"); + expand(p, INBREG, "\tli U1,0\n"); + } +} + +/* + * Structure assignment. + */ +static void +stasg(NODE *p) +{ + NODE *l = p->n_left; + int val = l->n_lval; + + /* R3 = dest, R4 = src, R5 = len */ + printf("\tli %s,%d\n", rnames[R5], p->n_stsize); + if (l->n_op == OREG) { + printf("\taddi %s,%s,%d\n", rnames[R3], rnames[regno(l)], val); + } else if (l->n_op == NAME) { +#if defined(ELFABI) + printf("\tli %s,", rnames[R3]); + adrput(stdout, l); + printf("@ha\n"); + printf("\taddi %s,%s,", rnames[R3], rnames[R3]); + adrput(stdout, l); + printf("@l\n"); +#elif defined(MACHOABI) + printf("\tli %s,ha16(", rnames[R3]); + adrput(stdout, l); + printf(")\n"); + printf("\taddi %s,%s,lo16(", rnames[R3], rnames[R3]); + adrput(stdout, l); + printf(")\n"); +#endif + } + if (kflag) { +#if defined(ELFABI) + printf("\tbl %s@got(30)\n", EXPREFIX "memcpy"); +#elif defined(MACHOABI) + printf("\tbl L%s$stub\n", EXPREFIX "memcpy"); + addstub(&stublist, EXPREFIX "memcpy"); +#endif + } else { + printf("\tbl %s\n", EXPREFIX "memcpy"); + } +} + +static void +fpemul(NODE *p) +{ + NODE *l = p->n_left; + char *ch = NULL; + + if (p->n_op == PLUS && p->n_type == FLOAT) ch = "addsf3"; + else if (p->n_op == PLUS && p->n_type == DOUBLE) ch = "adddf3"; + else if (p->n_op == PLUS && p->n_type == LDOUBLE) ch = "addtf3"; + + else if (p->n_op == MINUS && p->n_type == FLOAT) ch = "subsf3"; + else if (p->n_op == MINUS && p->n_type == DOUBLE) ch = "subdf3"; + else if (p->n_op == MINUS && p->n_type == LDOUBLE) ch = "subtf3"; + + else if (p->n_op == MUL && p->n_type == FLOAT) ch = "mulsf3"; + else if (p->n_op == MUL && p->n_type == DOUBLE) ch = "muldf3"; + else if (p->n_op == MUL && p->n_type == LDOUBLE) ch = "multf3"; + + else if (p->n_op == DIV && p->n_type == FLOAT) ch = "divsf3"; + else if (p->n_op == DIV && p->n_type == DOUBLE) ch = "divdf3"; + else if (p->n_op == DIV && p->n_type == LDOUBLE) ch = "divtf3"; + + else if (p->n_op == UMINUS && p->n_type == FLOAT) ch = "negsf2"; + else if (p->n_op == UMINUS && p->n_type == DOUBLE) ch = "negdf2"; + else if (p->n_op == UMINUS && p->n_type == LDOUBLE) ch = "negtf2"; + + else if (p->n_op == EQ && l->n_type == FLOAT) ch = "eqsf2"; + else if (p->n_op == EQ && l->n_type == DOUBLE) ch = "eqdf2"; + else if (p->n_op == EQ && l->n_type == LDOUBLE) ch = "eqtf2"; + + else if (p->n_op == NE && l->n_type == FLOAT) ch = "nesf2"; + else if (p->n_op == NE && l->n_type == DOUBLE) ch = "nedf2"; + else if (p->n_op == NE && l->n_type == LDOUBLE) ch = "netf2"; + + else if (p->n_op == GE && l->n_type == FLOAT) ch = "gesf2"; + else if (p->n_op == GE && l->n_type == DOUBLE) ch = "gedf2"; + else if (p->n_op == GE && l->n_type == LDOUBLE) ch = "getf2"; + + else if (p->n_op == LE && l->n_type == FLOAT) ch = "lesf2"; + else if (p->n_op == LE && l->n_type == DOUBLE) ch = "ledf2"; + else if (p->n_op == LE && l->n_type == LDOUBLE) ch = "letf2"; + + else if (p->n_op == GT && l->n_type == FLOAT) ch = "gtsf2"; + else if (p->n_op == GT && l->n_type == DOUBLE) ch = "gtdf2"; + else if (p->n_op == GT && l->n_type == LDOUBLE) ch = "gttf2"; + + else if (p->n_op == LT && l->n_type == FLOAT) ch = "ltsf2"; + else if (p->n_op == LT && l->n_type == DOUBLE) ch = "ltdf2"; + else if (p->n_op == LT && l->n_type == LDOUBLE) ch = "lttf2"; + + else if (p->n_op == SCONV && p->n_type == FLOAT) { + if (l->n_type == DOUBLE) ch = "truncdfsf2"; + else if (l->n_type == LDOUBLE) ch = "truncdfsf2"; + else if (l->n_type == ULONGLONG) ch = "floatunsdisf"; + else if (l->n_type == LONGLONG) ch = "floatdisf"; + else if (l->n_type == LONG) ch = "floatsisf"; + else if (l->n_type == ULONG) ch = "floatunsisf"; + else if (l->n_type == INT) ch = "floatsisf"; + else if (l->n_type == UNSIGNED) ch = "floatunsisf"; + } else if (p->n_op == SCONV && p->n_type == DOUBLE) { + if (l->n_type == FLOAT) ch = "extendsfdf2"; + else if (l->n_type == LDOUBLE) ch = "truncdfdf2"; + else if (l->n_type == ULONGLONG) ch = "floatunsdidf"; + else if (l->n_type == LONGLONG) ch = "floatdidf"; + else if (l->n_type == LONG) ch = "floatsidf"; + else if (l->n_type == ULONG) ch = "floatunssidf"; + else if (l->n_type == INT) ch = "floatsidf"; + else if (l->n_type == UNSIGNED) ch = "floatunssidf"; + } else if (p->n_op == SCONV && p->n_type == LDOUBLE) { + if (l->n_type == FLOAT) ch = "extendsfdf2"; + else if (l->n_type == DOUBLE) ch = "extenddfdf2"; + else if (l->n_type == ULONGLONG) ch = "floatunsdidf"; + else if (l->n_type == LONGLONG) ch = "floatdidf"; + else if (l->n_type == LONG) ch = "floatsidf"; + else if (l->n_type == ULONG) ch = "floatunssidf"; + else if (l->n_type == INT) ch = "floatsidf"; + else if (l->n_type == UNSIGNED) ch = "floatunsidf"; + } else if (p->n_op == SCONV && p->n_type == ULONGLONG) { + if (l->n_type == FLOAT) ch = "fixunssfdi"; + else if (l->n_type == DOUBLE) ch = "fixunsdfdi"; + else if (l->n_type == LDOUBLE) ch = "fixunsdfdi"; + } else if (p->n_op == SCONV && p->n_type == LONGLONG) { + if (l->n_type == FLOAT) ch = "fixsfdi"; + else if (l->n_type == DOUBLE) ch = "fixdfdi"; + else if (l->n_type == LDOUBLE) ch = "fixdfdi"; + } else if (p->n_op == SCONV && p->n_type == LONG) { + if (l->n_type == FLOAT) ch = "fixsfdi"; + else if (l->n_type == DOUBLE) ch = "fixdfdi"; + else if (l->n_type == LDOUBLE) ch = "fixdfdi"; + } else if (p->n_op == SCONV && p->n_type == ULONG) { + if (l->n_type == FLOAT) ch = "fixunssfdi"; + else if (l->n_type == DOUBLE) ch = "fixunsdfdi"; + else if (l->n_type == LDOUBLE) ch = "fixunsdfdi"; + } else if (p->n_op == SCONV && p->n_type == INT) { + if (l->n_type == FLOAT) ch = "fixsfsi"; + else if (l->n_type == DOUBLE) ch = "fixdfsi"; + else if (l->n_type == LDOUBLE) ch = "fixdfsi"; + } else if (p->n_op == SCONV && p->n_type == UNSIGNED) { + if (l->n_type == FLOAT) ch = "fixunssfsi"; + else if (l->n_type == DOUBLE) ch = "fixunsdfsi"; + else if (l->n_type == LDOUBLE) ch = "fixunsdfsi"; + } + + if (ch == NULL) comperr("ZF: op=0x%x (%d)\n", p->n_op, p->n_op); + + if (kflag) { +#if defined(ELFABI) + printf("\tbl __%s%s@got(30)" COM "soft-float\n", EXPREFIX, ch); +#elif defined(MACHOABI) + char buf[32]; + printf("\tbl L__%s%s$stub" COM "soft-float\n", EXPREFIX, ch); + snprintf(buf, 32, "__%s%s", EXPREFIX, ch); + addstub(&stublist, buf); +#endif + } else { + printf("\tbl __%s%s" COM "soft-float\n", EXPREFIX, ch); + } + + if (p->n_op >= EQ && p->n_op <= GT) + printf("\tcmpwi %s,0\n", rnames[R3]); +} + +/* + * http://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html#Integer-library-routines + */ + +static void +emul(NODE *p) +{ + char *ch = NULL; + + if (p->n_op == LS && DEUNSIGN(p->n_type) == LONGLONG) ch = "ashldi3"; + else if (p->n_op == LS && (DEUNSIGN(p->n_type) == LONG || + DEUNSIGN(p->n_type) == INT)) + ch = "ashlsi3"; + + else if (p->n_op == RS && p->n_type == ULONGLONG) ch = "lshrdi3"; + else if (p->n_op == RS && (p->n_type == ULONG || p->n_type == INT)) + ch = "lshrsi3"; + + else if (p->n_op == RS && p->n_type == LONGLONG) ch = "ashrdi3"; + else if (p->n_op == RS && (p->n_type == LONG || p->n_type == INT)) + ch = "ashrsi3"; + + else if (p->n_op == DIV && p->n_type == LONGLONG) ch = "divdi3"; + else if (p->n_op == DIV && (p->n_type == LONG || p->n_type == INT)) + ch = "divsi3"; + + else if (p->n_op == DIV && p->n_type == ULONGLONG) ch = "udivdi3"; + else if (p->n_op == DIV && (p->n_type == ULONG || + p->n_type == UNSIGNED)) + ch = "udivsi3"; + + else if (p->n_op == MOD && p->n_type == LONGLONG) ch = "moddi3"; + else if (p->n_op == MOD && (p->n_type == LONG || p->n_type == INT)) + ch = "modsi3"; + + else if (p->n_op == MOD && p->n_type == ULONGLONG) ch = "umoddi3"; + else if (p->n_op == MOD && (p->n_type == ULONG || + p->n_type == UNSIGNED)) + ch = "umodsi3"; + + else if (p->n_op == MUL && p->n_type == LONGLONG) ch = "muldi3"; + else if (p->n_op == MUL && (p->n_type == LONG || p->n_type == INT)) + ch = "mulsi3"; + + else if (p->n_op == UMINUS && p->n_type == LONGLONG) ch = "negdi2"; + else if (p->n_op == UMINUS && p->n_type == LONG) ch = "negsi2"; + + else ch = 0, comperr("ZE"); + if (kflag) { +#if defined(ELFABI) + printf("\tbl __%s%s@got(30)" COM "emulated op\n", EXPREFIX, ch); +#elif defined(MACHOABI) + char buf[32]; + printf("\tbl L__%s%s$stub" COM "emulated op\n", EXPREFIX, ch); + snprintf(buf, 32, "__%s%s", EXPREFIX, ch); + addstub(&stublist, buf); +#endif + } else { + printf("\tbl __%s%s" COM "emulated operation\n", EXPREFIX, ch); + } +} + +/* + * Floating-point conversions (int -> float/double & float/double -> int) + */ + +static void +ftoi(NODE *p) +{ + NODE *l = p->n_left; + + printf(COM "start conversion float/(l)double to int\n"); + + if (l->n_op != OREG) { + expand(p, 0, "\tstw AL,-4"); + printf("(%s)\n", rnames[SPREG]); + if (l->n_type == FLOAT) + expand(p, 0, "\tlfs A2,"); + else + expand(p, 0, "\tlfd A2,\n"); + printf("-4(%s)\n", rnames[SPREG]); + } else { + if (l->n_type == FLOAT) + expand(p, 0, "\tlfs A2,AL\n"); + else + expand(p, 0, "\tlfd A2,AL\n"); + } + + expand(p, 0, "\tfctiwz A2,A2\n"); + expand(p, 0, "\tstfd A2,"); + printf("-8(%s)\n", rnames[SPREG]); + expand(p, 0, "\tlwz A1,"); + printf("-4(%s)\n", rnames[SPREG]); + + printf(COM "end conversion\n"); +} + +static void +ftou(NODE *p) +{ + static int lab = 0; + NODE *l = p->n_left; + int lab1 = getlab2(); + int lab2 = getlab2(); + + printf(COM "start conversion of float/(l)double to unsigned\n"); + + if (lab == 0) { + lab = getlab2(); + expand(p, 0, "\t.data\n"); + printf(LABFMT ":\t.long 0x41e00000\n\t.long 0\n", lab); + expand(p, 0, "\t.text\n"); + } + + if (l->n_op != OREG) { + expand(p, 0, "\tstw AL,"); + printf("-4(%s)\n", rnames[SPREG]); + if (l->n_type == FLOAT) + expand(p, 0, "\tlfs A3,"); + else + expand(p, 0, "\tlfd A3,"); + printf("-4(%s)\n", rnames[SPREG]); + + } else { + if (l->n_type == FLOAT) + expand(p, 0, "\tlfs A3,AL\n"); + else + expand(p, 0, "\tlfd A3,AL\n"); + } + +#if 0 + if (kflag) { + expand(p, 0, "\taddis A1,"); + printf("%s,ha16(", rnames[R31]); + printf(LABFMT, lab); + printf("-L%s$pb)\n", cftnsp->soname ? cftnsp->soname : exname(cftnsp->sname)); + expand(p, 0, "\tlfd A2,lo16("); + printf(LABFMT, lab); + printf("-L%s$pb)\n", cftnsp->soname ? cftnsp->soname : exname(cftnsp->sname)); + expand(p, 0, "(A1)\n"); + } else { + expand(p, 0, "\tlfd A2,"); + printf(LABFMT "\n", lab); + } +#endif + +#if defined(ELFABI) + + expand(p, 0, "\taddis A1,"); + printf("%s," LABFMT "@ha\n", rnames[R31], lab); + expand(p, 0, "\tlfd A2,"); + printf(LABFMT "@l", lab); + expand(p, 0, "(A1)\n"); + +#elif defined(MACHOABI) + + expand(p, 0, "\taddis A1,"); + printf("%s,ha16(", rnames[R31]); + printf(LABFMT, lab); + if (kflag) + printf("-L%s$pb", cftnsp->soname ? cftnsp->soname : exname(cftnsp->sname)); + printf(")\n"); + expand(p, 0, "\tlfd A2,lo16("); + printf(LABFMT, lab); + if (kflag) + printf("-L%s$pb", cftnsp->soname ? cftnsp->soname : exname(cftnsp->sname)); + expand(p, 0, ")(A1)\n"); + +#endif + + expand(p, 0, "\tfcmpu cr7,A3,A2\n"); + printf("\tcror 30,29,30\n"); + printf("\tbeq cr7,"LABFMT "\n", lab1); + + expand(p, 0, "\tfctiwz A2,A3\n"); + expand(p, 0, "\tstfd A2,"); + printf("-8(%s)\n", rnames[SPREG]); + expand(p, 0, "\tlwz A1,"); + printf("-4(%s)\n", rnames[SPREG]); + printf("\tba " LABFMT "\n", lab2); + + deflab(lab1); + + expand(p, 0, "\tfsub A2,A3,A2\n"); + expand(p, 0, "\tfctiwz A2,A2\n"); + expand(p, 0, "\tstfd A2,"); + printf("-8(%s)\n", rnames[SPREG]); + expand(p, 0, "\tlwz A1,"); + printf("-4(%s)\n", rnames[SPREG]); + expand(p, 0, "\txoris A1,A1,0x8000\n"); + + deflab(lab2); + + printf(COM "end conversion\n"); +} + +static void +itof(NODE *p) +{ + static int labu = 0; + static int labi = 0; + int lab; + NODE *l = p->n_left; + + printf(COM "start conversion (u)int to float/(l)double\n"); + + if (labi == 0 && l->n_type == INT) { + labi = getlab2(); + expand(p, 0, "\t.data\n"); + printf(LABFMT ":\t.long 0x43300000\n\t.long 0x80000000\n", labi); + expand(p, 0, "\t.text\n"); + } else if (labu == 0 && l->n_type == UNSIGNED) { + labu = getlab2(); + expand(p, 0, "\t.data\n"); + printf(LABFMT ":\t.long 0x43300000\n\t.long 0x00000000\n", labu); + expand(p, 0, "\t.text\n"); + } + + if (l->n_type == INT) { + expand(p, 0, "\txoris A1,AL,0x8000\n"); + lab = labi; + } else { + lab = labu; + } + expand(p, 0, "\tstw A1,"); + printf("-4(%s)\n", rnames[SPREG]); + expand(p, 0, "\tlis A1,0x4330\n"); + expand(p, 0, "\tstw A1,"); + printf("-8(%s)\n", rnames[SPREG]); + expand(p, 0, "\tlfd A3,"); + printf("-8(%s)\n", rnames[SPREG]); + +#if 0 + if (kflag) { + expand(p, 0, "\taddis A1,"); + printf("%s,ha16(", rnames[R31]); + printf(LABFMT, lab); + printf("-L%s$pb)\n", cftnsp->soname ? cftnsp->soname : exname(cftnsp->sname)); + expand(p, 0, "\tlfd A2,lo16("); + printf(LABFMT, lab); + printf("-L%s$pb)\n", cftnsp->soname ? cftnsp->soname : exname(cftnsp->sname)); + expand(p, 0, "(A1)\n"); + } else { + expand(p, 0, "\tlfd A2,"); + printf(LABFMT "\n", lab); + } +#endif + +#if defined(ELFABI) + + expand(p, 0, "\taddis A1,"); + printf("%s," LABFMT "@ha\n", rnames[R31], lab); + expand(p, 0, "\tlfd A2,"); + printf(LABFMT "@l", lab); + expand(p, 0, "(A1)\n"); + +#elif defined(MACHOABI) + + expand(p, 0, "\taddis A1,"); + printf("%s,ha16(", rnames[R31]); + printf(LABFMT, lab); + if (kflag) + printf("-L%s$pb", cftnsp->soname ? cftnsp->soname : exname(cftnsp->sname)); + printf(")\n"); + expand(p, 0, "\tlfd A2,lo16("); + printf(LABFMT, lab); + if (kflag) + printf("-L%s$pb", cftnsp->soname ? cftnsp->soname : exname(cftnsp->sname)); + expand(p, 0, ")(A1)\n"); + +#endif + + expand(p, 0, "\tfsub A3,A3,A2\n"); + if (p->n_type == FLOAT) + expand(p, 0, "\tfrsp A3,A3\n"); + + printf(COM "end conversion\n"); +} + + +static void +fpconv(NODE *p) +{ + NODE *l = p->n_left; + +#ifdef PCC_DEBUG + if (p->n_op != SCONV) + cerror("fpconv 1"); +#endif + + if (DEUNSIGN(l->n_type) == INT) + itof(p); + else if (p->n_type == INT) + ftoi(p); + else if (p->n_type == UNSIGNED) + ftou(p); + else + cerror("unhandled floating-point conversion"); + +} + +void +zzzcode(NODE *p, int c) +{ + switch (c) { + + case 'C': /* floating-point conversions */ + fpconv(p); + break; + + case 'D': /* long long comparision */ + twollcomp(p); + break; + + case 'E': /* print out emulated ops */ + emul(p); + break; + + case 'F': /* print out emulate floating-point ops */ + fpemul(p); + break; + + case 'O': /* 64-bit left and right shift operators */ + shiftop(p); + break; + + case 'Q': /* emit struct assign */ + stasg(p); + break; + + default: + comperr("zzzcode %c", c); + } +} + +/*ARGSUSED*/ +int +rewfld(NODE *p) +{ + return(1); +} + +int canaddr(NODE *); +int +canaddr(NODE *p) +{ + int o = p->n_op; + + if (o == NAME || o == REG || o == ICON || o == OREG || + (o == UMUL && shumul(p->n_left, SOREG))) + return(1); + return 0; +} + +int +fldexpand(NODE *p, int cookie, char **cp) +{ + CONSZ val; + int shft; + + if (p->n_op == ASSIGN) + p = p->n_left; + + if (features(FEATURE_BIGENDIAN)) + shft = SZINT - UPKFSZ(p->n_rval) - UPKFOFF(p->n_rval); + else + shft = UPKFOFF(p->n_rval); + + switch (**cp) { + case 'S': + printf("%d", UPKFSZ(p->n_rval)); + break; + case 'H': + printf("%d", shft); + break; + case 'M': + case 'N': + val = (CONSZ)1 << UPKFSZ(p->n_rval); + --val; + val <<= shft; + printf(CONFMT, (**cp == 'M' ? val : ~val) & 0xffffffff); + break; + default: + comperr("fldexpand"); + } + return 1; +} + +/* + * Does the bitfield shape match? + */ +int +flshape(NODE *p) +{ + int o = p->n_op; + + if (o == OREG || o == REG || o == NAME) + return SRDIR; /* Direct match */ + if (o == UMUL && shumul(p->n_left, SOREG)) + return SROREG; /* Convert into oreg */ + return SRREG; /* put it into a register */ +} + +/* INTEMP shapes must not contain any temporary registers */ +/* XXX should this go away now? */ +int +shtemp(NODE *p) +{ + printf("; shtemp\n"); + return 0; +#if 0 + int r; + + if (p->n_op == STARG ) + p = p->n_left; + + switch (p->n_op) { + case REG: + return (!istreg(regno(p))); + + case OREG: + r = regno(p); + if (R2TEST(r)) { + if (istreg(R2UPK1(r))) + return(0); + r = R2UPK2(r); + } + return (!istreg(r)); + + case UMUL: + p = p->n_left; + return (p->n_op != UMUL && shtemp(p)); + } + + if (optype(p->n_op) != LTYPE) + return(0); + return(1); +#endif +} + +void +adrcon(CONSZ val) +{ + printf( CONFMT, val); +} + +void +conput(FILE *fp, NODE *p) +{ + int val = p->n_lval; + + switch (p->n_op) { + case ICON: + if (p->n_name[0] != '\0') { + fprintf(fp, "%s", p->n_name); + if (val) + fprintf(fp, "+%d", val); + } else { + if (GCLASS(p->n_type) == CLASSB) + fprintf(fp, CONFMT, p->n_lval >> 32); + else + fprintf(fp, "%d", val); + } + return; + + default: + comperr("illegal conput, p %p", p); + } +} + +/*ARGSUSED*/ +void +insput(NODE *p) +{ + comperr("insput"); +} + +/* + * Print lower or upper name of 64-bit register. + */ +static void +reg64name(int reg, int hi) +{ + int idx; + int off = 0; + + idx = (reg > R14R15 ? (2*(reg - R14R15) + R14) : (reg - R3R4 + R3)); + + if ((hi == HIREG && !features(FEATURE_BIGENDIAN)) || + (hi == LOWREG && features(FEATURE_BIGENDIAN))) + off = 1; + + fprintf(stdout, "%s" , rnames[idx + off]); +} + +/* + * Write out the upper address, like the upper register of a 2-register + * reference, or the next memory location. + */ +void +upput(NODE *p, int size) +{ + size /= SZCHAR; + switch (p->n_op) { + case REG: + reg64name(regno(p), HIREG); + break; + + case NAME: + case OREG: + if (features(FEATURE_BIGENDIAN)) + fprintf(stdout, "%d", (int)p->n_lval); + else + fprintf(stdout, "%d", (int)(p->n_lval + 4)); + fprintf(stdout, "(%s)", rnames[regno(p)]); + break; + + case ICON: + fprintf(stdout, CONFMT, p->n_lval >> 32); + break; + + default: + comperr("upput bad op %d size %d", p->n_op, size); + } +} + +void +adrput(FILE *io, NODE *p) +{ + /* output an address, with offsets, from p */ + + if (p->n_op == FLD) + p = p->n_left; + + switch (p->n_op) { + + case NAME: + if (p->n_name[0] != '\0') { + fputs(p->n_name, io); + if (p->n_lval != 0) + fprintf(io, "+" CONFMT, p->n_lval); + } else + fprintf(io, CONFMT, p->n_lval); + return; + + case OREG: + if (DEUNSIGN(p->n_type) == LONGLONG && + features(FEATURE_BIGENDIAN)) + fprintf(io, "%d", (int)(p->n_lval + 4)); + else + fprintf(io, "%d", (int)p->n_lval); + fprintf(io, "(%s)", rnames[regno(p)]); + return; + + case ICON: + /* addressable value of the constant */ + conput(io, p); + return; + + case REG: + if (GCLASS(regno(p)) == CLASSB) + reg64name(regno(p), LOWREG); + else + fprintf(io, "%s", rnames[regno(p)]); +#if 0 + switch (p->n_type) { + case DOUBLE: + case LDOUBLE: + if (features(FEATURE_HARDFLOAT)) { + fprintf(io, "%s", rnames[regno(p)]); + break; + } + /* FALL-THROUGH */ + case LONGLONG: + case ULONGLONG: + reg64name(regno(p), LOWREG); + break; + default: + fprintf(io, "%s", rnames[regno(p)]); + } +#endif + return; + + default: + comperr("illegal address, op %d, node %p", p->n_op, p); + return; + + } +} + +/* + * these mnemonics match the order of the preprocessor decls + * EQ, NE, LE, LT, GE, GT, ULE, ULT, UGE, UGT + */ + +static char * +ccbranches[] = { + "beq", /* branch if equal */ + "bne", /* branch if not-equal */ + "ble", /* branch if less-than-or-equal */ + "blt", /* branch if less-than */ + "bge", /* branch if greater-than-or-equal */ + "bgt", /* branch if greater-than */ + /* what should these be ? */ + "ble", /* branch if less-than-or-equal */ + "blt", /* branch if less-than */ + "bge", /* branch if greater-than-or-equal */ + "bgt", /* branch if greater-than */ + +}; + + +/* printf conditional and unconditional branches */ +void +cbgen(int o, int lab) +{ + if (o < EQ || o > UGT) + comperr("bad conditional branch: %s", opst[o]); + printf("\t%s " LABFMT "\n", ccbranches[o-EQ], lab); +} + +static int +argsize(NODE *p) +{ + TWORD t = p->n_type; + + if (t < LONGLONG || t == FLOAT || t > BTMASK) + return 4; + if (t == LONGLONG || t == ULONGLONG) + return 8; + if (t == DOUBLE || t == LDOUBLE) + return 8; + if (t == STRTY || t == UNIONTY) + return p->n_stsize; + comperr("argsize"); + return 0; +} + +static int +calc_args_size(NODE *p) +{ + int n = 0; + + if (p->n_op == CM) { + n += calc_args_size(p->n_left); + n += calc_args_size(p->n_right); + return n; + } + + n += argsize(p); + + return n; +} + + +static void +fixcalls(NODE *p, void *arg) +{ + int n = 0; + + switch (p->n_op) { + case STCALL: + case CALL: + n = calc_args_size(p->n_right); + if (n > p2maxstacksize) + p2maxstacksize = n; + /* FALLTHROUGH */ + case USTCALL: + case UCALL: + ++p2calls; + break; + case TEMP: + p2temps += argsize(p); + break; + } +} + +/* + * Must store floats in memory if there are two function calls involved. + */ +static int +storefloat(struct interpass *ip, NODE *p) +{ + int l, r; + + switch (optype(p->n_op)) { + case BITYPE: + l = storefloat(ip, p->n_left); + r = storefloat(ip, p->n_right); + if (p->n_op == CM) + return 0; /* arguments, don't care */ + if (callop(p->n_op)) + return 1; /* found one */ +#define ISF(p) ((p)->n_type == FLOAT || (p)->n_type == DOUBLE || \ + (p)->n_type == LDOUBLE) + if (ISF(p->n_left) && ISF(p->n_right) && l && r) { + /* must store one. store left */ + struct interpass *nip; + TWORD t = p->n_left->n_type; + NODE *ll; + int off; + + off = BITOOR(freetemp(szty(t))); + ll = mklnode(OREG, off, SPREG, t); + nip = ipnode(mkbinode(ASSIGN, ll, p->n_left, t)); + p->n_left = mklnode(OREG, off, SPREG, t); + DLIST_INSERT_BEFORE(ip, nip, qelem); + } + return l|r; + + case UTYPE: + l = storefloat(ip, p->n_left); + if (callop(p->n_op)) + l = 1; + return l; + default: + return 0; + } +} + +void +myreader(struct interpass *ipole) +{ + struct interpass *ip; + + p2calls = 0; + p2temps = 0; + p2maxstacksize = 0; + + DLIST_FOREACH(ip, ipole, qelem) { + if (ip->type != IP_NODE) + continue; + walkf(ip->ip_node, fixcalls, 0); + storefloat(ip, ip->ip_node); + } + + if (p2maxstacksize < NARGREGS*SZINT/SZCHAR) + p2maxstacksize = NARGREGS*SZINT/SZCHAR; + + p2framesize = ARGINIT/SZCHAR; /* stack ptr / return addr */ + p2framesize += 8; /* for R31 and R30 */ + p2framesize += p2maxautooff; /* autos */ + p2framesize += p2temps; /* TEMPs that aren't autos */ + if (p2calls != 0) + p2framesize += p2maxstacksize; /* arguments to functions */ + p2framesize += (ALSTACK/SZCHAR - 1); /* round to 16-byte boundary */ + p2framesize &= ~(ALSTACK/SZCHAR - 1); + +#if 0 + printf("!!! MYREADER\n"); + printf("!!! p2maxautooff = %d\n", p2maxautooff); + printf("!!! p2autooff = %d\n", p2autooff); + printf("!!! p2temps = %d\n", p2temps); + printf("!!! p2calls = %d\n", p2calls); + printf("!!! p2maxstacksize = %d\n", p2maxstacksize); +#endif + + if (x2debug) + printip(ipole); +} + +/* + * Remove some PCONVs after OREGs are created. + */ +static void +pconv2(NODE *p, void *arg) +{ + NODE *q; + + if (p->n_op == PLUS) { + if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) { + if (p->n_right->n_op != ICON) + return; + if (p->n_left->n_op != PCONV) + return; + if (p->n_left->n_left->n_op != OREG) + return; + q = p->n_left->n_left; + nfree(p->n_left); + p->n_left = q; + /* + * This will be converted to another OREG later. + */ + } + } +} + +void +mycanon(NODE *p) +{ + walkf(p, pconv2, 0); +} + +void +myoptim(struct interpass *ip) +{ +#ifdef PCC_DEBUG + if (x2debug) { + printf("myoptim\n"); + } +#endif +} + +/* + * Move data between registers. While basic registers aren't a problem, + * we have to handle the special case of overlapping composite registers. + * It might just be easier to modify the register allocator so that + * moves between overlapping registers isn't possible. + */ +void +rmove(int s, int d, TWORD t) +{ + switch (t) { + case LDOUBLE: + case DOUBLE: + if (features(FEATURE_HARDFLOAT)) { + printf("\tfmr %s,%s" COM "rmove\n", + rnames[d], rnames[s]); + break; + } + /* FALL-THROUGH */ + case LONGLONG: + case ULONGLONG: + if (s == d+1) { + /* dh = sl, copy low word first */ + printf("\tmr "); + reg64name(d, LOWREG); + printf(","); + reg64name(s, LOWREG); + printf("\n"); + printf("\tmr "); + reg64name(d, HIREG); + printf(","); + reg64name(s, HIREG); + printf("\n"); + } else { + /* copy high word first */ + printf("\tmr "); + reg64name(d, HIREG); + printf(","); + reg64name(s, HIREG); + printf("\n"); + printf("\tmr "); + reg64name(d, LOWREG); + printf(","); + reg64name(s, LOWREG); + printf("\n"); + } + break; + case FLOAT: + if (features(FEATURE_HARDFLOAT)) { + printf("\tfmr %s,%s" COM "rmove\n", + rnames[d], rnames[s]); + break; + } + /* FALL-THROUGH */ + default: + printf("\tmr %s,%s" COM "rmove\n", rnames[d], rnames[s]); + } +} + +/* + * For class c, find worst-case displacement of the number of + * registers in the array r[] indexed by class. + * + * On PowerPC, we have: + * + * 32 32-bit registers (2 reserved) + * 16 64-bit pseudo registers + * 32 floating-point registers + */ +int +COLORMAP(int c, int *r) +{ + int num = 0; + + switch (c) { + case CLASSA: + num += r[CLASSA]; + num += 2*r[CLASSB]; + return num < 30; + case CLASSB: + num += 2*r[CLASSB]; + num += r[CLASSA]; + return num < 16; + case CLASSC: + return num < 32; + case CLASSD: + return r[CLASSD] < DREGCNT; + } + return 0; /* XXX gcc */ +} + +/* + * Return a class suitable for a specific type. + */ +int +gclass(TWORD t) +{ + if (t == LONGLONG || t == ULONGLONG) + return CLASSB; + if (t == FLOAT || t == DOUBLE || t == LDOUBLE) { + if (features(FEATURE_HARDFLOAT)) + return CLASSC; + if (t == FLOAT) + return CLASSA; + else + return CLASSB; + } + return CLASSA; +} + +int +retreg(int t) +{ + int c = gclass(t); + if (c == CLASSB) + return R3R4; + else if (c == CLASSC) + return F1; + return R3; +} + +/* + * Calculate argument sizes. + */ +void +lastcall(NODE *p) +{ + NODE *op = p; + int size = 0; + +#ifdef PCC_DEBUG + if (x2debug) + printf("lastcall:\n"); +#endif + + p->n_qual = 0; + if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL) + return; + + for (p = p->n_right; p->n_op == CM; p = p->n_left) + size += argsize(p->n_right); + size += argsize(p); + op->n_qual = size; /* XXX */ +} + +/* + * Special shapes. + */ +int +special(NODE *p, int shape) +{ + int o = p->n_op; + + switch (shape) { + case SFUNCALL: + if (o == STCALL || o == USTCALL) + return SRREG; + break; + case SPCON: + if (o == ICON && p->n_name[0] == 0 && (p->n_lval & ~0x7fff) == 0) + return SRDIR; + break; + } + return SRNOPE; +} + +static int fset = FEATURE_BIGENDIAN | FEATURE_HARDFLOAT; + +/* + * Target-dependent command-line options. + */ +void +mflags(char *str) +{ + if (strcasecmp(str, "big-endian") == 0) { + fset |= FEATURE_BIGENDIAN; + } else if (strcasecmp(str, "little-endian") == 0) { + fset &= ~FEATURE_BIGENDIAN; + } else if (strcasecmp(str, "soft-float") == 0) { + fset &= ~FEATURE_HARDFLOAT; + } else if (strcasecmp(str, "hard-float") == 0) { + fset |= FEATURE_HARDFLOAT; + } else { + fprintf(stderr, "unknown m option '%s'\n", str); + exit(1); + } +} + +int +features(int mask) +{ + return ((fset & mask) == mask); +} +/* + * Do something target-dependent for xasm arguments. + * Supposed to find target-specific constraints and rewrite them. + */ +int +myxasm(struct interpass *ip, NODE *p) +{ + return 0; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/powerpc/macdefs.h b/compilers/pcc/pcc-1.0.0/arch/powerpc/macdefs.h new file mode 100644 index 00000000..8d6b53c8 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/powerpc/macdefs.h @@ -0,0 +1,407 @@ +/* $Id: macdefs.h,v 1.11 2010/11/26 17:06:31 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Machine-dependent defines for both passes. + */ + +/* + * Convert (multi-)character constant to integer. + */ +#define makecc(val,i) lastcon = (lastcon<<8)|((val<<24)>>24); + +/* + * Storage space requirements + */ +#define SZCHAR 8 +#define SZBOOL 32 +#define SZINT 32 +#define SZFLOAT 32 +#define SZDOUBLE 64 +#ifdef ELFABI +#define SZLDOUBLE 96 +#else +#define SZLDOUBLE 128 +#endif +#define SZLONG 32 +#define SZSHORT 16 +#define SZLONGLONG 64 +#define SZPOINT(t) 32 + +/* + * Alignment constraints + */ +#define ALCHAR 8 +#define ALBOOL 32 +#define ALINT 32 +#define ALFLOAT 32 +#define ALDOUBLE 32 +#ifdef ELFABI +#define ALLDOUBLE 32 +#else +#define ALLDOUBLE 128 +#endif +#define ALLONG 32 +#ifdef ELFABI +#define ALLONGLONG 64 +#else +#define ALLONGLONG 32 +#endif +#define ALSHORT 16 +#define ALPOINT 32 +#define ALSTRUCT 32 +#define ALSTACK (16*SZCHAR) + +/* + * Min/max values. + */ +#define MIN_CHAR -128 +#define MAX_CHAR 127 +#define MAX_UCHAR 255 +#define MIN_SHORT -32768 +#define MAX_SHORT 32767 +#define MAX_USHORT 65535 +#define MIN_INT -1 +#define MAX_INT 0x7fffffff +#define MAX_UNSIGNED 0xffffffff +#define MIN_LONG MIN_INT +#define MAX_LONG MAX_INT +#define MAX_ULONG MAX_UNSIGNED +#define MIN_LONGLONG 0x8000000000000000LL +#define MAX_LONGLONG 0x7fffffffffffffffLL +#define MAX_ULONGLONG 0xffffffffffffffffULL + +#define CHAR_UNSIGNED +#define BOOL_TYPE INT /* what used to store _Bool */ + +/* + * Use large-enough types. + */ +typedef long long CONSZ; +typedef unsigned long long U_CONSZ; +typedef long long OFFSZ; + +#define CONFMT "%lld" /* format for printing constants */ +#if defined(ELFABI) +#define LABFMT ".L%d" /* format for printing labels */ +#define REGPREFIX "%" /* format for printing registers */ +#elif defined(MACHOABI) +#define LABFMT "L%d" /* format for printing labels */ +#define REGPREFIX +#else +#error undefined ABI +#endif +#define STABLBL "LL%d" /* format for stab (debugging) labels */ + +#ifdef MACHOABI +#define STAB_LINE_ABSOLUTE /* S_LINE fields use absolute addresses */ +#endif + +#undef FIELDOPS /* no bit-field instructions */ + +#define ENUMSIZE(high,low) INT /* enums are always stored in full int */ + +/* Definitions mostly used in pass2 */ + +#define BYTEOFF(x) ((x)&03) +#define BITOOR(x) (x) /* bit offset to oreg offset XXX die! */ + +#define szty(t) (((t) == DOUBLE || (t) == LDOUBLE || \ + DEUNSIGN(t) == LONGLONG) ? 2 : 1) + +/* + * The PPC register definition are taken from apple docs. + * + * The classes used are: + * A - general registers + * B - 64-bit register pairs + * C - floating-point registers + */ + +#define R0 0 /* scratch register */ +#define R1 1 /* stack base pointer */ +#define R2 2 +#define R3 3 /* return register / argument 0 */ +#define R4 4 /* return register (for longlong) / argument 1 */ +#define R5 5 /* scratch register / argument 2 */ +#define R6 6 /* scratch register / argument 3 */ +#define R7 7 /* scratch register / argument 4 */ +#define R8 8 /* scratch register / argument 5 */ +#define R9 9 /* scratch register / argument 6 */ +#define R10 10 /* scratch register / argument 7 */ +#define R11 11 /* scratch register */ +#define R12 12 /* scratch register */ +#define R13 13 +#define R14 14 +#define R15 15 +#define R16 16 +#define R17 17 +#define R18 18 +#define R19 19 +#define R20 20 +#define R21 21 +#define R22 22 +#define R23 23 +#define R24 24 +#define R25 25 +#define R26 26 +#define R27 27 +#define R28 28 +#define R29 29 +#define R30 30 +#define R31 31 + +#define R3R4 32 +#define R4R5 33 +#define R5R6 34 +#define R6R7 35 +#define R7R8 36 +#define R8R9 37 +#define R9R10 38 +#define R14R15 39 +#define R16R17 40 +#define R18R19 41 +#define R20R21 42 +#define R22R23 43 +#define R24R25 44 +#define R26R27 45 +#define R28R29 46 +#define R30R31 47 + +#define F0 48 /* scratch register */ +#define F1 49 /* return value 0 / argument 0 */ +#define F2 50 /* return value 1 / argument 1 */ +#define F3 51 /* return value 2 / argument 2 */ +#define F4 52 /* return value 3 / argument 3 */ +#define F5 53 /* argument 4 */ +#define F6 54 /* argument 5 */ +#define F7 55 /* argument 6 */ +#define F8 56 /* argument 7 */ +#define F9 57 /* argument 8 */ +#define F10 58 /* argument 9 */ +#define F11 59 /* argument 10 */ +#define F12 60 /* argument 11 */ +#define F13 61 /* argument 12 */ +#define F14 62 +#define F15 63 +#define F16 64 +#define F17 65 +#define F18 66 +#define F19 67 +#define F20 68 +#define F21 69 +#define F22 70 +#define F23 71 +#define F24 72 +#define F25 73 +#define F26 74 +#define F27 75 +#define F28 76 +#define F29 77 +#define F30 78 +#define F31 79 + +#define NUMCLASS 3 +#define MAXREGS 64 /* XXX cannot have more than 64 */ + +#define RSTATUS \ + 0, /* R0 */ \ + 0, /* R1 */ \ + SAREG|TEMPREG, /* R2 */ \ + SAREG|TEMPREG, /* R3 */ \ + SAREG|TEMPREG, /* R4 */ \ + SAREG|TEMPREG, /* R5 */ \ + SAREG|TEMPREG, /* R6 */ \ + SAREG|TEMPREG, /* R7 */ \ + SAREG|TEMPREG, /* R8 */ \ + SAREG|TEMPREG, /* R9 */ \ + SAREG|TEMPREG, /* R10 */ \ + SAREG|TEMPREG, /* R11 */ \ + SAREG|TEMPREG, /* R12 */ \ + SAREG, /* R13 */ \ + SAREG, /* R14 */ \ + SAREG, /* R15 */ \ + SAREG, /* R16 */ \ + SAREG, /* R17 */ \ + SAREG, /* R18 */ \ + SAREG, /* R19 */ \ + SAREG, /* R20 */ \ + SAREG, /* R21 */ \ + SAREG, /* R22 */ \ + SAREG, /* R23 */ \ + SAREG, /* R24 */ \ + SAREG, /* R25 */ \ + SAREG, /* R26 */ \ + SAREG, /* R27 */ \ + SAREG, /* R28 */ \ + SAREG, /* R29 */ \ + SAREG, /* R30 */ \ + SAREG, /* R31 */ \ + \ + SBREG|TEMPREG, /* R3R4 */ \ + SBREG|TEMPREG, /* R4R5 */ \ + SBREG|TEMPREG, /* R5R6 */ \ + SBREG|TEMPREG, /* R6R7 */ \ + SBREG|TEMPREG, /* R7R8 */ \ + SBREG|TEMPREG, /* R8R9 */ \ + SBREG|TEMPREG, /* R9R10 */ \ + \ + SBREG, /* R14R15 */ \ + SBREG, /* R16R17 */ \ + SBREG, /* R18R19 */ \ + SBREG, /* R20R21 */ \ + SBREG, /* R22R23 */ \ + SBREG, /* R24R25 */ \ + SBREG, /* R26R2k */ \ + SBREG, /* R28R29 */ \ + SBREG, /* R30R31 */ \ + \ + SCREG|TEMPREG, /* F0 */ \ + SCREG|TEMPREG, /* F1 */ \ + SCREG|TEMPREG, /* F2 */ \ + SCREG|TEMPREG, /* F3 */ \ + SCREG|TEMPREG, /* F4 */ \ + SCREG|TEMPREG, /* F5 */ \ + SCREG|TEMPREG, /* F6 */ \ + SCREG|TEMPREG, /* F7 */ \ + SCREG|TEMPREG, /* F8 */ \ + SCREG|TEMPREG, /* F9 */ \ + SCREG|TEMPREG, /* F10 */ \ + SCREG|TEMPREG, /* F11 */ \ + SCREG|TEMPREG, /* F12 */ \ + SCREG|TEMPREG, /* F13 */ \ + SCREG, /* F14 */ \ + SCREG, /* F15 */ \ + +#define ROVERLAP \ + { -1 }, { -1 }, { -1 }, \ + { R3R4, -1 }, { R3R4, R4R5, -1 }, \ + { R4R5, R5R6, -1 }, { R5R6, R6R7, -1 }, \ + { R6R7, R7R8, -1 }, { R7R8, R8R9, -1 }, \ + { R8R9, R9R10, -1 }, { R9R10, -1 }, \ + { -1 }, { -1 }, { -1 }, \ + { R14R15, -1 }, { R14R15, -1 }, \ + { R16R17, -1 }, { R16R17, -1 }, \ + { R18R19, -1 }, { R18R19, -1 }, \ + { R20R21, -1 }, { R20R21, -1 }, \ + { R22R23, -1 }, { R22R23, -1 }, \ + { R24R25, -1 }, { R24R25, -1 }, \ + { R26R27, -1 }, { R26R27, -1 }, \ + { R28R29, -1 }, { R28R29, -1 }, \ + { R30R31, -1 }, { R30R31, -1 }, \ + \ + { R3, R4, R4R5, -1 }, { R4, R5, R3R4, R5R6, -1 }, \ + { R5, R6, R4R5, R6R7, -1 }, { R6, R7, R5R6, R7R8, -1 }, \ + { R7, R8, R6R7, R8R9, -1 }, { R8, R9, R7R8, R8R9, -1 }, \ + { R9, R10, R8R9, -1 }, \ + { R14, R15, -1 }, { R16, R17, -1 }, \ + { R18, R19, -1 }, { R20, R21, -1 }, \ + { R22, R23, -1 }, { R24, R25, -1 }, \ + { R26, R27, -1 }, { R28, R29, -1 }, \ + { R30, R31, -1 }, \ + \ + { -1 }, { -1 }, { -1 }, { -1 }, \ + { -1 }, { -1 }, { -1 }, { -1 }, \ + { -1 }, { -1 }, { -1 }, { -1 }, \ + { -1 }, { -1 }, { -1 }, { -1 }, \ + +/* + * According to the ABI documents, there isn't really a frame pointer; + * all references to data on the stack (autos and parameters) are + * indexed relative to the stack pointer. However, pcc isn't really + * capable of running in this manner, and expects a frame pointer. + */ +#define SPREG R1 /* stack pointer */ +#define FPREG R30 /* frame pointer */ +#define GOTREG R31 /* global offset table (PIC) */ + +#ifdef FPREG +#define ARGINIT (24*8) /* # bits above fp where arguments start */ +#define AUTOINIT (8*8) /* # bits above fp where automatics start */ +#define BACKAUTO /* stack grows negatively for automatics */ +#define BACKTEMP /* stack grows negatively for temporaries */ +#else +#define ARGINIT (24*8) /* # bits above fp where arguments start */ +#define AUTOINIT (56*8) /* # bits above fp where automatics start */ +#endif + +/* Return a register class based on the type of the node */ +#define PCLASS(p) (1 << gclass((p)->n_type)) + +#define GCLASS(x) ((x) < 32 ? CLASSA : ((x) < 48 ? CLASSB : CLASSC)) +#define DECRA(x,y) (((x) >> (y*6)) & 63) /* decode encoded regs */ +#define ENCRA(x,y) ((x) << (6+y*6)) /* encode regs in int */ +#define ENCRD(x) (x) /* Encode dest reg in n_reg */ +#define RETREG(x) retreg(x) + +int COLORMAP(int c, int *r); +int retreg(int ty); + +#define SHSTR (MAXSPECIAL+1) /* short struct */ +#define SFUNCALL (MAXSPECIAL+2) /* struct assign after function call */ +#define SPCON (MAXSPECIAL+3) /* positive constant */ + +int features(int f); +#define FEATURE_BIGENDIAN 0x00010000 +#define FEATURE_PIC 0x00020000 +#define FEATURE_HARDFLOAT 0x00040000 + +struct stub { + struct { struct stub *q_forw, *q_back; } link; + char *name; +}; +extern struct stub stublist; +extern struct stub nlplist; +void addstub(struct stub *list, char *name); + +#define TARGET_STDARGS +#define TARGET_BUILTINS \ + { "__builtin_stdarg_start", powerpc_builtin_stdarg_start }, \ + { "__builtin_va_arg", powerpc_builtin_va_arg }, \ + { "__builtin_va_end", powerpc_builtin_va_end }, \ + { "__builtin_va_copy", powerpc_builtin_va_copy }, \ + { "__builtin_frame_address", powerpc_builtin_frame_address }, \ + { "__builtin_return_address", powerpc_builtin_return_address }, + +#define NODE struct node +struct node; +NODE *powerpc_builtin_stdarg_start(NODE *f, NODE *a, unsigned int); +NODE *powerpc_builtin_va_arg(NODE *f, NODE *a, unsigned int); +NODE *powerpc_builtin_va_end(NODE *f, NODE *a, unsigned int); +NODE *powerpc_builtin_va_copy(NODE *f, NODE *a, unsigned int); +NODE *powerpc_builtin_frame_address(NODE *f, NODE *a, unsigned int); +NODE *powerpc_builtin_return_address(NODE *f, NODE *a, unsigned int); +#undef NODE + +#define NARGREGS 8 + +#ifdef ELFABI +#define COM " # " +#else +#define COM " ; " +#endif diff --git a/compilers/pcc/pcc-1.0.0/arch/powerpc/order.c b/compilers/pcc/pcc-1.0.0/arch/powerpc/order.c new file mode 100644 index 00000000..61782cdf --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/powerpc/order.c @@ -0,0 +1,408 @@ +/* $Id: order.c,v 1.8 2009/01/07 11:44:03 gmcgarry Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +# include "pass2.h" + +#include + +int canaddr(NODE *); + +/* + * Check size of offset in OREG. Called by oregok() to see if an + * OREG can be generated. + * + * returns 0 if it can, 1 otherwise. + */ +int +notoff(TWORD t, int r, CONSZ off, char *cp) +{ +#if 0 + if (off >= 32767 || off <= -32768) + printf("; notoff %lld TOO BIG!\n", off); +#endif + if (cp && cp[0]) return 1; + return (off >= 32768 || off <= -32769); +} + +/* + * Generate instructions for an OREG. + * Called by swmatch(). + */ +void +offstar(NODE *p, int shape) +{ + NODE *r; + + if (x2debug) + printf("offstar(%p)\n", p); + + if (isreg(p)) + return; /* Is already OREG */ + + r = p->n_right; + if( p->n_op == PLUS || p->n_op == MINUS ){ + if( r->n_op == ICON ){ + if (isreg(p->n_left) == 0) + (void)geninsn(p->n_left, INAREG); + /* Converted in ormake() */ + return; + } + } + (void)geninsn(p, INAREG); +} + +/* + * Unable to convert to OREG (notoff() returned failure). Output + * suitable instructions to replace OREG. + */ +void +myormake(NODE *q) +{ + NODE *p; + + if (x2debug) + printf("myormake(%p)\n", q); + + p = q->n_left; + + /* + * This handles failed OREGs conversions, due to the offset + * being too large for an OREG. + */ + if ((p->n_op == PLUS || p->n_op == MINUS) && p->n_right->n_op == ICON) { + if (isreg(p->n_left) == 0) + (void)geninsn(p->n_left, INAREG); + if (isreg(p->n_right) == 0) + (void)geninsn(p->n_right, INAREG); + (void)geninsn(p, INAREG); + } else if (p->n_op == REG) { + q->n_op = OREG; + q->n_lval = p->n_lval; + q->n_rval = p->n_rval; + tfree(p); + } +} + +/* + * Shape matches for UMUL. Cooperates with offstar(). + */ +int +shumul(NODE *p, int shape) +{ + + if (x2debug) + printf("shumul(%p)\n", p); + + /* Turns currently anything into OREG on x86 */ + if (shape & SOREG) + return SROREG; + return SRNOPE; +} + +/* + * Rewrite operations on binary operators (like +, -, etc...). + * Called as a result of table lookup. + */ +int +setbin(NODE *p) +{ + + if (x2debug) + printf("setbin(%p)\n", p); + return 0; + +} + +/* setup for assignment operator */ +int +setasg(NODE *p, int cookie) +{ + if (x2debug) + printf("setasg(%p)\n", p); + return(0); +} + +/* setup for unary operator */ +int +setuni(NODE *p, int cookie) +{ + return 0; +} + +/* + * Special handling of some instruction register allocation. + */ +struct rspecial * +nspecial(struct optab *q) +{ + if (x2debug) + printf("nspecial: op=%d, visit=0x%x: %s", q->op, q->visit, q->cstring); + + switch (q->op) { + + /* soft-float stuff */ + case RS: + case LS: + if (q->lshape == SBREG) { + static struct rspecial s[] = { + { NLEFT, R3R4 }, + { NRIGHT, R5 }, + { NRES, R3R4 }, + { 0 }, + }; + return s; + } else if (q->lshape == SAREG) { + static struct rspecial s[] = { + { NLEFT, R3 }, + { NRIGHT, R4 }, + { NRES, R3 }, + { 0 }, + }; + return s; + } + + cerror("nspecial LS/RS"); + break; + + case UMINUS: + case SCONV: + if (q->lshape == SBREG && q->rshape == SAREG) { + static struct rspecial s[] = { + { NLEFT, R3R4 }, + { NRES, R3 }, + { 0 } + }; + return s; + } else if (q->lshape == SAREG && q->rshape == SBREG) { + static struct rspecial s[] = { + { NLEFT, R3 }, + { NRES, R3R4 }, + { 0 } + }; + return s; + } else if (q->lshape == SAREG && q->rshape == SAREG) { + static struct rspecial s[] = { + { NLEFT, R3 }, + { NRES, R3 }, + { 0 } + }; + return s; + } else if (q->lshape == SBREG && q->rshape == SBREG) { + static struct rspecial s[] = { + { NLEFT, R3R4 }, + { NRES, R3R4 }, + { 0 } + }; + return s; + } else if (q->lshape == SCREG && q->rshape == SBREG) { + static struct rspecial s[] = { + { NLEFT, F1 }, + { NEVER, F0 }, /* stomped on */ + { NRES, R3R4 }, + { 0 } + }; + return s; + } else if (q->lshape == SBREG && q->rshape == SCREG) { + static struct rspecial s[] = { + { NLEFT, R3R4 }, + { NEVER, F0 }, /* stomped on */ + { NRES, F1 }, + { 0 } + }; + return s; + } else { + static struct rspecial s[] = { + { NOLEFT, R0 }, + { 0 } }; + return s; + } + + break; + + case OPLOG: + if (q->lshape == SBREG) { + static struct rspecial s[] = { + { NLEFT, R3R4 }, + { NRIGHT, R5R6 }, + { NRES, R3 }, + { 0 } + }; + return s; + } else if (q->lshape == SAREG) { + static struct rspecial s[] = { + { NLEFT, R3 }, + { NRIGHT, R4 }, + { NRES, R3 }, + { 0 } + }; + return s; + } + + cerror("nspecial oplog"); + break; + + case PLUS: + case MINUS: + case MUL: + case DIV: + case MOD: + if (q->lshape == SBREG && + (q->ltype & (TDOUBLE|TLDOUBLE|TLONGLONG|TULONGLONG))) { + static struct rspecial s[] = { + { NLEFT, R3R4 }, + { NRIGHT, R5R6 }, + { NRES, R3R4 }, + { 0 } + }; + return s; + } else if (q->lshape == SAREG && q->ltype & TFLOAT) { + static struct rspecial s[] = { + { NLEFT, R3 }, + { NRIGHT, R4 }, + { NRES, R3 }, + { 0 } + }; + return s; + } else if (q->lshape == SAREG) { + static struct rspecial s[] = { + { NOLEFT, R0 }, + { 0 } }; + return s; + } + + cerror("nspecial mul"); + break; + + case STASG: + { + static struct rspecial s[] = { + { NEVER, R3 }, + { NRIGHT, R4 }, + { NEVER, R5 }, + { 0 } }; + return s; + } + break; + + case OPLTYPE: + { + if (q->visit & SAREG) { + static struct rspecial s[] = { + { NEVER, R0 }, + { 0 } }; + return s; + } + } + break; + + case ASSIGN: + if (q->lshape & SNAME) { + static struct rspecial s[] = { + { NEVER, R0 }, + { 0 } }; + return s; + } else if (q->rshape & SNAME) { + static struct rspecial s[] = { + { NOLEFT, R0 }, + { 0 } }; + return s; + } else if (q->lshape & SOREG) { + static struct rspecial s[] = { + { NOLEFT, R0 }, + { 0 } }; + return s; + } else if (q->rshape & SOREG) { + static struct rspecial s[] = { + { NORIGHT, R0 }, + { 0 } }; + return s; + } + /* fallthough */ + + case UMUL: + case AND: + case OR: + case ER: + { + static struct rspecial s[] = { + { NOLEFT, R0 }, + { 0 } }; + return s; + } + + default: + break; + } + + comperr("nspecial entry %d: %s", q - table, q->cstring); + return 0; /* XXX gcc */ +} + +/* + * Set evaluation order of a binary node if it differs from default. + */ +int +setorder(NODE *p) +{ + return 0; /* nothing differs on x86 */ +} + +/* + * Set registers "live" at function calls (like arguments in registers). + * This is for liveness analysis of registers. + */ +int * +livecall(NODE *p) +{ + static int r[] = { R10, R9, R8, R7, R6, R5, R4, R3, R30, R31, -1 }; + int num = 1; + + if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL) + return &r[8-0]; + + for (p = p->n_right; p->n_op == CM; p = p->n_left) + num += szty(p->n_right->n_type); + num += szty(p->n_right->n_type); + + num = (num > 8 ? 8 : num); + + return &r[8 - num]; +} + +/* + * Signal whether the instruction is acceptable for this target. + */ +int +acceptable(struct optab *op) +{ + if ((op->visit & FEATURE_PIC) != 0) + return (kflag != 0); + return features(op->visit & 0xffff0000); +} diff --git a/compilers/pcc/pcc-1.0.0/arch/powerpc/table.c b/compilers/pcc/pcc-1.0.0/arch/powerpc/table.c new file mode 100644 index 00000000..5f81d776 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/powerpc/table.c @@ -0,0 +1,1806 @@ +/* $Id: table.c,v 1.18 2010/11/26 17:06:31 ragge Exp $ */ +/*- + * Copyright (c) 2007 Gregory McGarry + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * A template has five logical sections: + * + * 1) subtree (operator); goal to achieve (cookie) + * 2) left node descendent of operator (node class; type) + * 3) right node descendent of operator (node class; type) + * 4) resource requirements (number of scratch registers); + * subtree rewriting rule + * 5) emitted instructions + */ + +#include "pass2.h" + +#define TUWORD TUNSIGNED|TULONG +#define TSWORD TINT|TLONG +#define TWORD TUWORD|TSWORD + +#if defined(ELFABI) +#define HA16(x) # x "@ha" +#define LO16(x) # x "@l" +#elif defined(MACHOABI) +#define HA16(x) "ha16(" # x ")" +#define LO16(x) "lo16(" # x ")" +#else +#error undefined ABI +#endif + +struct optab table[] = { +/* First entry must be an empty entry */ +{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", }, + +/* PCONVs are not necessary */ +{ PCONV, INAREG, + SAREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + 0, RLEFT, + COM "pointer conversion\n", }, + +/* + * Conversions of integral types + */ + +{ SCONV, INAREG, + SAREG, TCHAR|TUCHAR, + SAREG, TCHAR|TUCHAR, + 0, RLEFT, + COM "convert between (u)char and (u)char\n", }, + +{ SCONV, INAREG, + SAREG, TSHORT|TUSHORT, + SAREG, TSHORT|TUSHORT, + 0, RLEFT, + COM "convert between (u)short and (u)short\n", }, + +{ SCONV, INAREG, + SAREG, TPOINT|TWORD, + SAREG, TWORD, + 0, RLEFT, + COM "convert a pointer/word to an int\n", }, + +{ SCONV, INAREG, + SAREG, TPOINT, + SAREG, TPOINT, + 0, RLEFT, + COM "convert pointers\n", }, + +{ SCONV, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + 0, RLEFT, + COM "convert (u)longlong to (u)longlong\n", }, + +{ SCONV, INAREG, + SAREG, TCHAR, + SAREG, TSHORT|TSWORD, + NASL|NAREG, RESC1, + " extsb A1,AL" COM "convert char to short/int\n", }, + +{ SCONV, INAREG, + SAREG, TUCHAR, + SAREG, TSHORT|TSWORD, + 0, RLEFT, + COM "convert uchar to short/int\n", }, + +{ SCONV, INAREG, + SAREG, TUCHAR, + SAREG, TUSHORT|TUWORD, + 0, RLEFT, + COM "convert uchar to ushort/unsigned\n", }, + +/* XXX is this necessary? */ +{ SCONV, INAREG, + SAREG, TCHAR, + SAREG, TUSHORT|TUWORD, + NSPECIAL|NAREG|NASL, RESC1, + " extsb A1,AL" COM "convert char to ushort/unsigned\n", }, + +{ SCONV, INBREG | FEATURE_BIGENDIAN, + SAREG, TUCHAR|TUSHORT|TUNSIGNED, + SBREG, TLONGLONG|TULONGLONG, + NBREG, RESC1, + " mr U1,AL" COM "convert uchar/ushort/uint to (u)longlong\n" + " li A1,0\n", }, + +{ SCONV, INBREG, + SAREG, TUCHAR|TUSHORT|TUNSIGNED, + SBREG, TLONGLONG|TULONGLONG, + NBREG, RESC1, + " mr A1,AL" COM "convert uchar/ushort/uint to (u)longlong\n" + " li U1,0\n", }, + +{ SCONV, INBREG | FEATURE_BIGENDIAN, + SAREG, TCHAR|TSHORT|TSWORD, + SBREG, TULONGLONG|TLONGLONG, + NBREG, RESC1, + " mr U1,AL" COM "convert char/short/int to ulonglong\n" + " srawi A1,AL,31\n", }, + +{ SCONV, INBREG, + SAREG, TCHAR|TSHORT|TSWORD, + SBREG, TULONGLONG|TLONGLONG, + NBREG, RESC1, + " mr A1,AL" COM "convert char/short/int to ulonglong\n" + " srawi U1,AL,31\n", }, + +{ SCONV, INAREG, + SAREG, TSHORT|TUSHORT, + SAREG, TCHAR|TUCHAR, + NSPECIAL|NAREG|NASL, RESC1, + " andi. A1,AL,255" COM "convert (u)short to (u)char\n", }, + +/* XXX is this really necessary? */ +{ SCONV, INAREG, + SAREG, TSHORT, + SAREG, TWORD, + NAREG|NASL, RESC1, + " extsh A1,AL" COM "convert short to int\n", }, + +{ SCONV, INAREG, + SAREG, TUSHORT, + SAREG, TWORD, + NSPECIAL|NAREG|NASL, RESC1, + COM "convert ushort to word\n", }, + +{ SCONV, INAREG, + SAREG, TWORD, + SAREG, TCHAR|TUCHAR, + NAREG|NASL|NSPECIAL, RESC1, + " andi. A1,AL,255" COM "convert (u)int to (u)char\n", }, + +{ SCONV, INAREG, + SAREG, TWORD, + SAREG, TSHORT|TUSHORT, + NAREG|NASL|NSPECIAL, RESC1, + " andi. A1,AL,65535" COM "convert (u)int to (u)short\n", }, + +{ SCONV, INAREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TCHAR|TUCHAR, + NAREG|NSPECIAL, RESC1, + " andi. A1,AL,255" COM "(u)longlong to (u)char\n", }, + +{ SCONV, INAREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TSHORT|TUSHORT, + NAREG|NSPECIAL, RESC1, + " andi. A1,AL,65535" COM "(u)longlong to (u)short\n", }, + +{ SCONV, INAREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TWORD, + NAREG, RESC1, + " mr A1,AL" COM "convert (u)longlong to (u)int/long\n", }, + +/* conversions on load from memory */ + +{ SCONV, INAREG, + SOREG, TCHAR, + SAREG, TWORD, + NASL|NAREG|NSPECIAL, RESC1, + " lbz A1,AL" COM "convert char to int/long\n" + " extsb A1,A1\n", }, + +{ SCONV, INAREG, + SOREG, TUCHAR, + SAREG, TWORD, + NASL|NAREG|NSPECIAL, RESC1, + " lbz A1,AL" COM "convert uchar to int/long\n", }, + +{ SCONV, INAREG, + SOREG, TSHORT, + SAREG, TWORD, + NASL|NAREG|NSPECIAL, RESC1, + " lha A1,AL" COM "convert short to int/long\n", }, + +{ SCONV, INAREG, + SOREG, TUSHORT, + SAREG, TWORD, + NASL|NAREG|NSPECIAL, RESC1, + " lhz A1,AL" COM "convert ushort to int/long\n", }, + +{ SCONV, INAREG, + SOREG, TLONGLONG|TULONGLONG, + SAREG, TCHAR|TUCHAR, + NAREG|NSPECIAL, RESC1, + " lwz A1,AL" COM "(u)longlong to (u)char\n" + " andi. A1,A1,255\n", }, + +{ SCONV, INAREG, + SOREG, TLONGLONG|TULONGLONG, + SAREG, TSHORT|TUSHORT, + NAREG|NSPECIAL, RESC1, + " lwz A1,AL" COM "(u)longlong to (u)short\n" + " andi. A1,A1,65535\n", }, + +{ SCONV, INAREG, + SOREG, TLONGLONG|TULONGLONG, + SAREG, TWORD, + NAREG|NSPECIAL, RESC1, + " lwz A1,AL" COM "(u)longlong to (u)int\n", }, + +/* + * floating-point conversions + * + * There doesn't appear to be an instruction to move values between + * the floating-point registers and the general-purpose registers. + * So values are bounced into memory... + */ + +{ SCONV, INCREG | FEATURE_HARDFLOAT, + SCREG, TFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + 0, RLEFT, + COM "convert float to (l)double\n", }, + +/* soft-float */ +{ SCONV, INBREG, + SAREG, TFLOAT, + SBREG, TDOUBLE|TLDOUBLE, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +{ SCONV, INCREG | FEATURE_HARDFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TFLOAT, + NCREG, RESC1, + " frsp A1,AL" COM "convert (l)double to float\n", }, + +/* soft-float */ +{ SCONV, INAREG, + SBREG, TDOUBLE|TLDOUBLE, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +{ SCONV, INCREG | FEATURE_HARDFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + 0, RLEFT, + COM "convert (l)double to (l)double\n", }, + +/* soft-float */ +{ SCONV, INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SBREG, TDOUBLE|TLDOUBLE, + 0, RLEFT, + COM "convert (l)double to (l)double (soft-float)\n", }, + +{ SCONV, INCREG | FEATURE_HARDFLOAT, + SAREG, TWORD, + SCREG, TFLOAT|TDOUBLE|TLDOUBLE, + 2*NCREG|NAREG, RESC3, + "ZC", }, + +/* soft-float */ +{ SCONV, INAREG, + SAREG, TWORD, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +/* soft-float */ +{ SCONV, INBREG, + SAREG, TWORD, + SBREG, TDOUBLE|TLDOUBLE, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +{ SCONV, INAREG | FEATURE_HARDFLOAT, + SOREG, TFLOAT|TDOUBLE|TLDOUBLE, + SAREG, TWORD, + 2*NCREG|NAREG, RESC1, + "ZC", }, + +/* soft-float */ +{ SCONV, INAREG, + SAREG, TFLOAT, + SAREG, TWORD, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +/* soft-float */ +{ SCONV, INAREG, + SBREG, TDOUBLE|TLDOUBLE, + SAREG, TWORD, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +{ SCONV, INCREG | FEATURE_HARDFLOAT, + SBREG, TLONGLONG|TULONGLONG, + SCREG, TFLOAT|TDOUBLE|TLDOUBLE, + NSPECIAL|NCREG, RESC1, + "ZF", }, + +/* soft-float */ +{ SCONV, INAREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +/* soft-float */ +{ SCONV, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TDOUBLE|TLDOUBLE, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +{ SCONV, INBREG | FEATURE_HARDFLOAT, + SCREG, TFLOAT|TDOUBLE|TLDOUBLE, + SBREG, TLONGLONG|TULONGLONG, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +/* soft-float */ +{ SCONV, INBREG, + SAREG, TFLOAT, + SBREG, TLONGLONG|TULONGLONG, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +/* soft-float */ +{ SCONV, INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SBREG, TLONGLONG|TULONGLONG, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +/* + * Subroutine calls. + */ + +{ CALL, FOREFF, + SCON, TANY, + SANY, TANY, + 0, 0, + " bl CL" COM "call (args, no result) to scon\n", }, + +{ UCALL, FOREFF, + SCON, TANY, + SANY, TANY, + 0, 0, + " bl CL" COM "call (no args, no result) to scon\n", }, + +{ CALL, INAREG, + SCON, TANY, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, /* should be 0 */ + " bl CL" COM "call (args, result) to scon\n", }, + +{ UCALL, INAREG, + SCON, TANY, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, /* should be 0 */ + " bl CL" COM "call (no args, result) to scon\n", }, + +{ CALL, INBREG, + SCON, TANY, + SBREG, TLONGLONG|TULONGLONG, + NBREG|NBSL, RESC1, /* should be 0 */ + " bl CL" COM "call (args, result) to scon\n", }, + +{ UCALL, INBREG, + SCON, TANY, + SBREG, TLONGLONG|TULONGLONG, + NBREG|NBSL, RESC1, /* should be 0 */ + " bl CL" COM "call (no args, result) to scon\n", }, + +{ CALL, INCREG | FEATURE_HARDFLOAT, + SCON, TANY, + SCREG, TFLOAT|TDOUBLE|TLDOUBLE, + NCREG|NCSL, RESC1, /* should be 0 */ + " bl CL" COM "call (args, result) to scon\n", }, + +{ UCALL, INCREG | FEATURE_HARDFLOAT, + SCON, TANY, + SCREG, TFLOAT|TDOUBLE|TLDOUBLE, + NCREG|NCSL, RESC1, /* should be 0 */ + " bl CL" COM "call (no args, result) to scon\n", }, + +{ CALL, INAREG, + SCON, TANY, + SAREG, TFLOAT, + NAREG|NASL, RESC1, /* should be 0 */ + " bl CL" COM "call (args, result) to scon\n", }, + +{ UCALL, INAREG, + SCON, TANY, + SAREG, TFLOAT, + NAREG|NASL, RESC1, /* should be 0 */ + " bl CL" COM "call (no args, result) to scon\n", }, + +{ CALL, INBREG, + SCON, TANY, + SBREG, TDOUBLE|TLDOUBLE, + NBREG|NBSL, RESC1, /* should be 0 */ + " bl CL" COM "call (args, result) to scon\n", }, + +{ UCALL, INBREG, + SCON, TANY, + SBREG, TDOUBLE|TLDOUBLE, + NBREG|NBSL, RESC1, /* should be 0 */ + " bl CL" COM "call (no args, result) to scon\n", }, + + + +{ CALL, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, 0, + " mtctr AL" COM "call (args, no result) to reg\n" + " bctrl\n", }, + +{ UCALL, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, 0, + " mtctr AL" COM "call (no args, no result) to reg\n" + " bctrl\n", }, + +{ CALL, INAREG, + SAREG, TANY, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG, RESC1, + " mtctr AL" COM "call (args, result) to reg\n" + " bctrl\n", }, + +{ UCALL, INAREG, + SAREG, TANY, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG, RESC1, + " mtctr AL" COM "call (no args, result) to reg\n" + " bctrl\n", }, + +/* struct return */ +{ USTCALL, FOREFF, + SCON, TANY, + SANY, TANY, + 0, 0, + " bl CL\n", }, + +{ USTCALL, INAREG, + SCON, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + " bl CL\n", }, + +{ USTCALL, INAREG, + SAREG, TANY, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG, RESC1, + " mtctr AL" + " bctrl\n", }, + +{ STCALL, FOREFF, + SCON, TANY, + SANY, TANY, + 0, 0, + " bl CL\n", }, + +{ STCALL, INAREG, + SCON, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + " bl CL\n", }, + +{ STCALL, INAREG, + SAREG, TANY, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " mtctr AL" + " bctrl\n", }, + +/* + * The next rules handle all binop-style operators. + */ + +/* XXX AL cannot be R0 */ +{ PLUS, INAREG, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SSCON, TANY, + NAREG|NASL|NSPECIAL, RESC1, + " addi A1,AL,AR" COM "addition of constant\n", }, + +/* XXX AL cannot be R0 */ +{ PLUS, INAREG|FORCC, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SSCON, TANY, + NAREG|NASL|NSPECIAL, RESC1|RESCC, + " addic. A1,AL,AR" COM "addition of constant\n", }, + +{ PLUS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SSCON, TANY, + NBREG|NBSL, RESC1, + " addic A1,AL,AR" COM "64-bit addition of constant\n" + " addze U1,UL\n", }, + +{ PLUS, INAREG, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL|NSPECIAL, RESC1, + " add A1,AL,AR\n", }, + +{ PLUS, INAREG|FORCC, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL|NSPECIAL, RESC1|RESCC, + " add. A1,AL,AR\n", }, + +{ PLUS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NBREG|NBSL, RESC1, + " addc A1,AL,AR" COM "64-bit add\n" + " adde U1,UL,UR\n", }, + +{ PLUS, INCREG | FEATURE_HARDFLOAT, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, + " fadds A1,AL,AR" COM "float add\n", }, + +{ PLUS, INAREG, + SAREG, TFLOAT, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +{ PLUS, INCREG | FEATURE_HARDFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + NCREG|NCSL, RESC1, + " fadd A1,AL,AR" COM "(l)double add\n", }, + +/* soft-float */ +{ PLUS, INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SBREG, TDOUBLE|TLDOUBLE, + NSPECIAL|NBREG|NBSL, RESC1, + "ZF", }, + +{ MINUS, INAREG, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SSCON, TANY, + NAREG|NASL|NSPECIAL, RESC1, + " addi A1,AL,-AR\n", }, + +{ MINUS, INAREG|FORCC, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SSCON, TANY, + NAREG|NASL|NSPECIAL, RESC1|RESCC, + " addic. A1,AL,-AR\n", }, + +{ MINUS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SSCON, TANY, + NBREG|NBSL, RESC1, + " addic A1,AL,-AR\n" + " addme U1,UL\n", }, + +{ MINUS, INAREG, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL|NSPECIAL, RESC1, + " subf A1,AR,AL\n", }, + +{ MINUS, INAREG|FORCC, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL|NSPECIAL, RESC1|RESCC, + " subf. A1,AR,AL\n", }, + +{ MINUS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NBREG|NBSL, RESC1, + " subfc A1,AR,AL" COM "64-bit subtraction\n" + " subfe U1,UR,UL\n", }, + +{ MINUS, INCREG | FEATURE_HARDFLOAT, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG, RESC1, + " fsubs A1,AL,AR\n", }, + +{ MINUS, INAREG, + SAREG, TFLOAT, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +{ MINUS, INCREG | FEATURE_HARDFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + NCREG|NCSL, RESC1, + " fsub A1,AL,AR" COM "(l)double sub\n", }, + +/* soft-float */ +{ MINUS, INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SBREG, TDOUBLE|TLDOUBLE, + NSPECIAL|NBREG|NBSL, RESC1, + "ZF", }, + + +/* + * The next rules handle all shift operators. + */ + +{ LS, INAREG, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " slw A1,AL,AR" COM "left shift\n", }, + +{ LS, INAREG|FORCC, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " slw. A1,AL,AR" COM "left shift\n", }, + +{ LS, INAREG, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SCON, TANY, + NAREG|NASL, RESC1, + " slwi A1,AL,AR" COM "left shift by constant\n", }, + +{ LS, INAREG|FORCC, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SCON, TANY, + NAREG|NASL, RESC1, + " slwi. A1,AL,AR" COM "left shift by constant\n", }, + +{ LS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SCON, TANY, + NBREG, RESC1, + "ZO", }, + +{ LS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TANY, + NSPECIAL|NBREG, RESC1, + "ZE", }, + +{ RS, INAREG, + SAREG, TUWORD|TUSHORT|TUCHAR, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " srw A1,AL,AR" COM "right shift\n", }, + +{ RS, INAREG, + SAREG, TSWORD|TSHORT|TCHAR, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " sraw A1,AL,AR" COM "arithmetic right shift\n", }, + +{ RS, INAREG|FORCC, + SAREG, TUWORD|TUSHORT|TUCHAR, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " srw. A1,AL,AR" COM "right shift\n", }, + +{ RS, INAREG|FORCC, + SAREG, TSWORD|TSHORT|TCHAR, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " sraw. A1,AL,AR" COM "arithmetic right shift\n", }, + +{ RS, INAREG, + SAREG, TUWORD|TUSHORT|TUCHAR, + SCON, TANY, + NAREG|NASL, RESC1, + " srwi A1,AL,AR" COM "right shift by constant\n", }, + +{ RS, INAREG, + SAREG, TSWORD|TSHORT|TCHAR, + SCON, TANY, + NAREG|NASL, RESC1, + " srawi A1,AL,AR" COM "arithmetic right shift by constant\n", }, + +{ RS, INAREG|FORCC, + SAREG, TUWORD|TUSHORT|TUCHAR, + SCON, TANY, + NAREG|NASL, RESC1, + " srwi. A1,AL,AR" COM "right shift by constant\n", }, + +{ RS, INAREG|FORCC, + SAREG, TSWORD|TSHORT|TCHAR, + SCON, TANY, + NAREG|NASL, RESC1, + " srawi. A1,AL,AR" COM "right shift by constant\n", }, + +{ RS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SCON, TANY, + NBREG, RESC1, + "ZO" }, + +{ RS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SAREG, TANY, + NSPECIAL|NBREG, RESC1, + "ZE", }, + +/* + * The next rules takes care of assignments. "=". + */ + +{ ASSIGN, FOREFF|INAREG, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SSCON, TANY, + 0, RDEST, + " li AL,AR\n", }, + +{ ASSIGN, FOREFF|INBREG, + SBREG, TLONGLONG|TULONGLONG, + SSCON, TANY, + 0, RDEST, + " li AL,AR\n" + " li UL,UR\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SCON, TANY, + 0, RDEST, + " lis AL," HA16(AR) "\n" + " addi AL,AL," LO16(AR) "\n", }, + +{ ASSIGN, FOREFF|INBREG, + SBREG, TLONGLONG|TULONGLONG, + SCON, TANY, + 0, RDEST, + " lis AL," HA16(AR) "\n" + " addi AL,AL," LO16(AR) "\n" + " lis UL," HA16(UR) "\n" + " addi UL,UL," LO16(UR) "\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TWORD|TPOINT, + SOREG, TWORD|TPOINT, + NSPECIAL, RDEST, + " lwz AL,AR" COM "assign oreg to reg\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TWORD|TPOINT, + SNAME, TWORD|TPOINT, + NSPECIAL, RDEST, + " lis AL," HA16(AR) COM "assign sname to reg\n" + " lwz AL," LO16(AR) "(AL)\n", }, + +{ ASSIGN, FOREFF|INBREG, + SBREG, TLONGLONG|TULONGLONG, + SOREG, TLONGLONG|TULONGLONG, + NSPECIAL, RDEST, + " lwz AL,AR" COM "assign llong to reg\n" + " lwz UL,UR\n" }, + +{ ASSIGN, FOREFF|INAREG, + SBREG, TLONGLONG|TULONGLONG, + SNAME, TLONGLONG|TULONGLONG, + NSPECIAL, RDEST, + " lis AL," HA16(AR) COM "assign 64-bit sname to reg\n" + " lwz AL," LO16(AR) "(AL)\n" + " lis UL," HA16(UR) "\n" + " lwz UL," LO16(UR) "(UL)\n", }, + +{ ASSIGN, FOREFF|INBREG, + SBREG, TLONGLONG|TULONGLONG, + SOREG, TSWORD, + NSPECIAL, RDEST, + " lwz AL,AR" COM "load int/pointer into llong\n" + " srawi UL,AR,31\n" }, + +{ ASSIGN, FOREFF|INBREG, + SBREG, TLONGLONG|TULONGLONG, + SOREG, TUNSIGNED|TPOINT, + NSPECIAL, RDEST, + " lwz AL,AR" COM "load uint/pointer into (u)llong\n" + " li UL,0\n" }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TUCHAR, + SOREG, TUCHAR, + NSPECIAL, RDEST, + " lbz AL,AR\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TUCHAR, + SNAME, TUCHAR, + NSPECIAL, RDEST, + " lis AL," HA16(AR) COM "assign uchar sname to reg\n" + " lbz AL," LO16(AR) "(AL)\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TCHAR, + SOREG, TCHAR, + NSPECIAL, RDEST, + " lbz AL,AR\n" + " extsb AL,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TCHAR, + SNAME, TCHAR, + NSPECIAL, RDEST, + " lis AL," HA16(AR) COM "assign char sname to reg\n" + " lbz AL," LO16(AR) "(AL)\n" + " extsb AL,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TWORD|TPOINT, + SOREG, TSHORT, + NSPECIAL, RDEST, + " lha AL,AR\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TWORD|TPOINT, + SOREG, TUSHORT, + NSPECIAL, RDEST, + " lhz AL,AR\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TWORD, + SNAME, TSHORT, + NSPECIAL, RDEST, + " lis AL," HA16(AR) "\n" + " lha AL," LO16(AR) "(AL)\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TWORD, + SNAME, TUSHORT, + NSPECIAL, RDEST, + " lis AL," HA16(AR) "\n" + " lhz AL," LO16(AR) "(AL)\n", }, + +{ ASSIGN, FOREFF|INAREG, + SOREG, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + NSPECIAL, RDEST, + " stw AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SNAME, TWORD|TPOINT, + SAREG, TWORD|TPOINT, + NAREG|NSPECIAL, RDEST, + " lis A1," HA16(AL) COM "assign reg to sname\n" + " stw AR," LO16(AL) "(A1)\n", }, + +{ ASSIGN, FOREFF|INBREG, + SOREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NSPECIAL, RDEST, + " stw AR,AL" COM "store 64-bit value\n" + " stw UR,UL\n", }, + +{ ASSIGN, FOREFF|INBREG, + SNAME, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NBREG|NSPECIAL, RDEST, + " lis A1," HA16(AL) COM "assign reg to 64-bit sname\n" + " stw AR," LO16(AL) "(A1)\n" + " lis U1," HA16(UL) "\n" + " stw UR," LO16(UL) "(U1)\n", }, + +{ ASSIGN, FOREFF|INAREG, + SOREG, TCHAR|TUCHAR, + SAREG, TCHAR|TUCHAR, + NSPECIAL, RDEST, + " stb AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SNAME, TCHAR|TUCHAR, + SAREG, TCHAR|TUCHAR, + NAREG|NSPECIAL, RDEST, + " lis A1," HA16(AL) "\n" + " stb AR," LO16(AL) "(A1)\n", }, + +{ ASSIGN, FOREFF|INAREG, + SOREG, TSHORT|TUSHORT, + SAREG, TSHORT|TUSHORT, + NSPECIAL, RDEST, + " sth AR,AL\n", }, + +{ ASSIGN, FOREFF|INAREG, + SNAME, TSHORT|TUSHORT, + SAREG, TSHORT|TUSHORT, + NAREG|NSPECIAL, RDEST, + " lis A1," HA16(AL) "\n" + " sth AR," LO16(AL) "(A1)\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + 0, RDEST, + " mr AL,AR" COM "assign AR to AL\n", }, + +{ ASSIGN, FOREFF|INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + 0, RDEST, + " mr AL,AR" COM "assign UR:AR to UL:AL\n" + " mr UL,UR\n", }, + +{ ASSIGN, FOREFF|INAREG, + SFLD, TANY, + SAREG, TANY, + 3*NAREG, RDEST, + " lis A3," HA16(M) COM "bit-field assignment\n" + " addi A3,A3," LO16(M) "\n" + " lwz A2,AL\n" + " slwi A1,AR,H\n" + " and A1,A1,A3\n" + " not A3,A3\n" + " and A2,A2,A3\n" + " or A2,A2,A1\n" + " stw A2,AL\n" + "F mr AD,AR\n" + "F slwi AD,AD,32-S\n" + "F srwi AD,AD,32-S\n", }, + +{ STASG, INAREG|FOREFF, + SOREG|SNAME, TANY, + SAREG, TPTRTO|TANY, + NSPECIAL, RDEST, + "ZQ", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT, + SOREG, TFLOAT, + SCREG, TFLOAT, + 0, RDEST, + " stfs AR,AL" COM "store float\n", }, + +/* soft-float */ +{ ASSIGN, FOREFF|INAREG, + SOREG, TFLOAT, + SAREG, TFLOAT, + 0, RDEST, + " stw AR,AL" COM "store float (soft-float)\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT, + SNAME, TFLOAT, + SCREG, TFLOAT, + NAREG, RDEST, + " lis A1," HA16(AL) "\n" + " stfs AR," LO16(AL) "(A1)\n", }, + +/* soft-float */ +{ ASSIGN, FOREFF|INAREG, + SNAME, TFLOAT, + SAREG, TFLOAT, + NAREG, RDEST, + " lis A1," HA16(AL) "\n" + " stw AR," LO16(AL) "(A1)\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT, + SCREG, TFLOAT, + SOREG, TFLOAT, + 0, RDEST, + " lfs AL,AR" COM "load float\n", }, + +/* soft-float */ +{ ASSIGN, FOREFF|INAREG, + SAREG, TFLOAT, + SOREG, TFLOAT, + 0, RDEST, + " lwz AL,AR" COM "load float (soft-float)\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT, + SCREG, TFLOAT, + SNAME, TFLOAT, + NAREG, RDEST, + " lis A1," HA16(AR) "\n" + " lfs AL," LO16(AR) "(A1)\n", }, + +/* soft-float */ +{ ASSIGN, FOREFF|INAREG, + SAREG, TFLOAT, + SNAME, TFLOAT, + NAREG, RDEST, + " lis A1," HA16(AR) "\n" + " lwz AL," LO16(AR) "(A1)\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT, + SCREG, TFLOAT, + SCREG, TFLOAT, + 0, RDEST, + " fmr AL,AR" COM "assign AR to AL\n", }, + +/* soft-float */ +{ ASSIGN, FOREFF|INAREG, + SAREG, TFLOAT, + SAREG, TFLOAT, + 0, RDEST, + " mr AL,AR" COM "assign AR to AL\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT, + SOREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + 0, RDEST, + " stfd AR,AL" COM "store (l)double\n", }, + +/* soft-float */ +{ ASSIGN, FOREFF|INBREG, + SOREG, TDOUBLE|TLDOUBLE, + SBREG, TDOUBLE|TLDOUBLE, + 0, RDEST, + " stw AR,AL" COM "store (l)double (soft-float)\n" + " stw UR,UL\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT, + SNAME, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + NAREG, RDEST, + " lis A1," HA16(AL) "\n" + " stfd AR," LO16(AL) "(A1)\n", }, + +/* soft-float */ +{ ASSIGN, FOREFF|INBREG, + SNAME, TDOUBLE|TLDOUBLE, + SBREG, TDOUBLE|TLDOUBLE, + NAREG, RDEST, + " lis A1," HA16(AL) "\n" + " stw AR," LO16(AL) "(A1)\n" + " lis A1," HA16(UL) "\n" + " stw UR," LO16(UL) "(A1)\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + SOREG, TDOUBLE|TLDOUBLE, + 0, RDEST, + " lfd AL,AR" COM "load (l)double\n", }, + +/* soft-float */ +{ ASSIGN, FOREFF|INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SOREG, TDOUBLE|TLDOUBLE, + 0, RDEST, + " lwz AL,AR" COM "load (l)double (soft-float)\n" + " lwz UL,UR\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + SNAME, TDOUBLE|TLDOUBLE, + NAREG, RDEST, + " lis A1," HA16(AR) "\n" + " lfd AL," LO16(AR) "(A1)\n", }, + +/* soft-float */ +{ ASSIGN, FOREFF|INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SNAME, TDOUBLE|TLDOUBLE, + NAREG, RDEST, + " lis A1," HA16(AR) "\n" + " lwz AL," LO16(AR) "(A1)\n" + " lis A1," HA16(UR) "\n" + " lwz UL," LO16(UR) "(A1)\n", }, + +{ ASSIGN, FOREFF|INCREG | FEATURE_HARDFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + 0, RDEST, + " fmr AL,AR" COM "assign AR to AL\n", }, + +/* soft-float */ +{ ASSIGN, FOREFF|INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SBREG, TDOUBLE|TLDOUBLE, + 0, RDEST, + " mr AL,AR" COM "assign AR to AL\n" + " mr UL,UR\n", }, + +/* + * DIV/MOD/MUL + */ + +{ DIV, INAREG, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + NAREG|NASL, RESC1, + " divwu A1,AL,AR\n", }, + +{ DIV, INAREG|FORCC, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + NAREG|NASL, RESC1|RESCC, + " divwu. A1,AL,AR\n", }, + +{ DIV, INAREG, + SAREG, TWORD|TSHORT|TCHAR, + SAREG, TWORD|TSHORT|TCHAR, + NAREG|NASL, RESC1, + " divw A1,AL,AR\n", }, + +{ DIV, INAREG|FORCC, + SAREG, TWORD|TSHORT|TCHAR, + SAREG, TWORD|TSHORT|TCHAR, + NAREG|NASL, RESC1|RESCC, + " divw. A1,AL,AR\n", }, + +{ DIV, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NSPECIAL|NBREG, RESC1, + "ZE", }, + +{ DIV, INCREG | FEATURE_HARDFLOAT, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG|NCSR, RESC1, + " fdivs A1,AL,AR" COM "float divide\n", }, + +/* soft-float */ +{ DIV, INAREG, + SAREG, TFLOAT, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +{ DIV, INCREG | FEATURE_HARDFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + NCREG|NCSR, RESC1, + " fdiv A1,AL,AR" COM "(l)double divide\n", }, + +/* soft-float */ +{ DIV, INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SBREG, TDOUBLE|TLDOUBLE, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +{ MOD, INAREG, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + NAREG, RESC1, + " divwu A1,AL,AR" COM "unsigned modulo\n" + " mullw A1,A1,AR\n" + " subf A1,A1,AL\n", }, + +{ MOD, INAREG, + SAREG, TWORD|TSHORT|TCHAR, + SAREG, TWORD|TSHORT|TCHAR, + NAREG, RESC1, + " divw A1,AL,AR" COM "signed modulo\n" + " mullw A1,A1,AR\n" + " subf A1,A1,AL\n", }, + +{ MOD, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NSPECIAL|NBREG, RESC1, + "ZE", }, + +{ MUL, INAREG, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SSCON, TANY, + NAREG|NASL, RESC1, + " mulli A1,AL,AR\n", }, + +{ MUL, INAREG|FORCC, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SSCON, TANY, + NAREG|NASL, RESC1|RESCC, + " mulli. A1,AL,AR\n", }, + +{ MUL, INAREG, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " mullw A1,AL,AR\n", }, + +{ MUL, INAREG|FORCC, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1|RESCC, + " mullw. A1,AL,AR\n", }, + +{ MUL, INBREG, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NBREG, RESC1, + " mullw A1,AL,AR\n" + " mulhw U1,AL,AR\n", }, + +{ MUL, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NBREG, RESC1, + " mullw A1,AL,AR\n" + " mulhw U1,AL,AR\n", }, + +{ MUL, INCREG | FEATURE_HARDFLOAT, + SCREG, TFLOAT, + SCREG, TFLOAT, + NCREG|NCSR, RESC1, + " fmuls A1,AL,AR" COM "float multiply\n", }, + +/* soft-float */ +{ MUL, INAREG, + SAREG, TFLOAT, + SAREG, TFLOAT, + NSPECIAL|NAREG, RESC1, + "ZF", }, + +{ MUL, INCREG | FEATURE_HARDFLOAT, + SCREG, TDOUBLE|TLDOUBLE, + SCREG, TDOUBLE|TLDOUBLE, + NCREG|NCSR, RESC1, + " fmul A1,AL,AR" COM "(l)double multiply\n", }, + +/* soft-float */ +{ MUL, INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SBREG, TDOUBLE|TLDOUBLE, + NSPECIAL|NBREG, RESC1, + "ZF", }, + +/* + * Indirection operators. + */ + +{ UMUL, INAREG, + SANY, TANY, + SOREG|SNAME, TWORD|TPOINT, + NAREG|NSPECIAL, RESC1, + " lwz A1,AL" COM "word load\n", }, + +{ UMUL, INAREG, + SANY, TANY, + SOREG|SNAME, TCHAR, + NAREG|NSPECIAL, RESC1, + " lbz A1,AL" COM "char load\n" + " extsb A1,A1\n", }, + +{ UMUL, INAREG, + SANY, TANY, + SOREG|SNAME, TUCHAR, + NAREG|NSPECIAL, RESC1, + " lbz A1,AL" COM "uchar load\n", }, + +{ UMUL, INAREG, + SANY, TANY, + SOREG|SNAME, TSHORT, + NAREG|NSPECIAL, RESC1, + " lha A1,AL" COM "short load\n", }, + +{ UMUL, INAREG, + SANY, TANY, + SOREG|SNAME, TUSHORT, + NAREG|NSPECIAL, RESC1, + " lhz A1,AL" COM "ushort load\n", }, + +{ UMUL, INBREG, + SANY, TANY, + SOREG|SNAME, TLONGLONG|TULONGLONG, + NBREG, RESC1, + " lwz A1,AL" COM "64-bit load\n" + " lwz U1,UL\n", }, + +{ UMUL, INCREG | FEATURE_HARDFLOAT, + SANY, TANY, + SOREG|SNAME, TFLOAT, + NCREG, RESC1, + " lfs A1,AL" COM "float load\n", }, + +{ UMUL, INAREG, + SANY, TANY, + SOREG|SNAME, TFLOAT, + NAREG, RESC1, + " lwz A1,AL" COM "float load (soft-float)\n", }, + +{ UMUL, INCREG | FEATURE_HARDFLOAT, + SANY, TANY, + SOREG|SNAME, TDOUBLE|TLDOUBLE, + NCREG, RESC1, + " lfd A1,AL" COM "(l)double load\n", }, + +{ UMUL, INBREG, + SANY, TANY, + SOREG|SNAME, TDOUBLE|TLDOUBLE, + NSPECIAL|NBREG, RESC1, + " lwz A1,AL" COM "(l)double load (soft-float)\n" + " lwz U1,UL\n", }, + +#if 0 +{ UMUL, INAREG, + SANY, TANY, + SAREG, TWORD|TPOINT, + NAREG, RESC1, + " lwz A1,(AL)" COM "word load\n", }, +#endif + +/* + * Logical/branching operators + */ + +/* compare with constant */ +{ OPLOG, FORCC, + SAREG, TSWORD|TSHORT|TCHAR, + SSCON, TANY, + 0, RESCC, + " cmpwi AL,AR\n", }, + +/* compare with constant */ +{ OPLOG, FORCC, + SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, + SSCON, TANY, + 0, RESCC, + " cmplwi AL,AR\n", }, + +/* compare with register */ +{ OPLOG, FORCC, + SAREG, TSWORD|TSHORT|TCHAR, + SAREG, TSWORD|TSHORT|TCHAR, + 0, RESCC, + " cmpw AL,AR\n", }, + +/* compare with register */ +{ OPLOG, FORCC, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + 0, RESCC, + " cmplw AL,AR\n", }, + +/* compare with register */ +{ OPLOG, FORCC, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + 0, RESCC, + "ZD", }, + +/* compare with register */ +{ OPLOG, FORCC | FEATURE_HARDFLOAT, + SCREG, TFLOAT|TDOUBLE|TLDOUBLE, + SCREG, TFLOAT|TDOUBLE|TLDOUBLE, + 0, RESCC, + " fcmpu 0,AL,AR\n", }, + +/* soft-float */ +{ OPLOG, FORCC, + SAREG, TFLOAT, + SAREG, TFLOAT, + NSPECIAL, RESCC, + "ZF\n", }, + +/* soft-float */ +{ OPLOG, FORCC, + SBREG, TDOUBLE|TLDOUBLE, + SBREG, TDOUBLE|TLDOUBLE, + NSPECIAL, RESCC, + "ZF", }, + +{ OPLOG, FORCC, + SANY, TANY, + SANY, TANY, + REWRITE, 0, + "diediedie!", }, + +/* AND/OR/ER */ +{ AND, INAREG, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL|NSPECIAL, RESC1|RESCC, + " and A1,AL,AR\n", }, + +{ AND, INAREG|FORCC, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL|NSPECIAL, RESC1, + " and. A1,AL,AR\n", }, + +/* AR must be positive */ +{ AND, INAREG|FORCC, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SPCON, TANY, + NAREG|NASL|NSPECIAL, RESC1|RESCC, + " andi. A1,AL,AR\n", }, + +{ AND, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NBREG|NBSL, RESC1, + " and A1,AL,AR" COM "64-bit and\n" + " and U1,UL,UR\n" }, + +{ AND, INBREG|FORCC, + SBREG, TLONGLONG|TULONGLONG, + SPCON, TANY, + NBREG|NBSL, RESC1|RESCC, + " andi. A1,AL,AR" COM "64-bit and with constant\n" + " li U1,0\n" }, + +{ OR, INAREG, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL|NSPECIAL, RESC1, + " or A1,AL,AR\n", }, + +{ OR, INAREG|FORCC, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL|NSPECIAL, RESC1|RESCC, + " or. A1,AL,AR\n", }, + +{ OR, INAREG, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SPCON, TANY, + NAREG|NASL, RESC1, + " ori A1,AL,AR\n", }, + +{ OR, INAREG|FORCC, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SPCON, TANY, + NAREG|NASL, RESC1|RESCC, + " ori. A1,AL,AR\n", }, + +{ OR, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NBREG|NBSL, RESC1, + " or A1,AL,AR" COM "64-bit or\n" + " or U1,UL,UR\n" }, + +{ OR, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SPCON, TANY, + NBREG|NBSL, RESC1, + " ori A1,AL,AR" COM "64-bit or with constant\n" }, + +{ OR, INBREG|FORCC, + SBREG, TLONGLONG|TULONGLONG, + SPCON, TANY, + NBREG|NBSL, RESC1|RESCC, + " ori. A1,AL,AR" COM "64-bit or with constant\n" }, + +{ ER, INAREG, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL|NSPECIAL, RESC1, + " xor A1,AL,AR\n", }, + +{ ER, INAREG|FORCC, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL|NSPECIAL, RESC1|RESCC, + " xor. A1,AL,AR\n", }, + +{ ER, INAREG, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SPCON, TANY, + NAREG|NASL|NSPECIAL, RESC1, + " xori A1,AL,AR\n", }, + +{ ER, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SBREG, TLONGLONG|TULONGLONG, + NBREG|NBSL, RESC1, + " xor A1,AL,AR" COM "64-bit xor\n" + " xor U1,UL,UR\n" }, + +{ ER, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SPCON, TANY, + NBREG|NBSL, RESC1, + " xori A1,AL,AR" COM "64-bit xor with constant\n" }, + +/* + * Jumps. + */ +{ GOTO, FOREFF, + SCON, TANY, + SANY, TANY, + 0, RNOP, + " b LL\n", }, + +{ GOTO, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, RNOP, + " mtctr AL\n" + " bctr\n", }, + +/* + * Convert LTYPE to reg. + */ + +#if defined(ELFABI) +{ OPLTYPE, INAREG | FEATURE_PIC, + SANY, TANY, + SNAME, TANY, + NAREG, RESC1, + " lwz A1,AL" COM "elfabi pic load\n", }, +#endif + +{ OPLTYPE, INBREG, + SANY, TANY, + SOREG, TLONGLONG|TULONGLONG, + NBREG, RESC1, + " lwz A1,AL" COM "load llong from memory\n" + " lwz U1,UL\n", }, + +{ OPLTYPE, INBREG, + SANY, TANY, + SNAME, TLONGLONG|TULONGLONG, + NBREG, RESC1, + " lis A1," HA16(AL) COM "load llong from sname\n" + " lwz A1," LO16(AL) "(A1)\n" + " lis U1," HA16(UL) "\n" + " lwz U1," LO16(UL) "(U1)\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SOREG, TWORD|TPOINT, + NAREG, RESC1, + " lwz A1,AL" COM "load word from memory\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SNAME, TWORD|TPOINT, + NAREG|NSPECIAL, RESC1, + " lis A1," HA16(AL) COM "load word from sname\n" + " lwz A1," LO16(AL) "(A1)\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SOREG, TCHAR, + NAREG, RESC1, + " lbz A1,AL" COM "load char from memory\n" + " extsb A1,A1\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SNAME, TCHAR, + NAREG|NSPECIAL, RESC1, + " lis A1," HA16(AL) COM "load char from sname\n" + " lbz A1," LO16(AL) "(A1)\n" + " extsb A1,A1\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SOREG, TUCHAR, + NAREG, RESC1, + " lbz A1,AL" COM "load uchar from memory\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SNAME, TUCHAR, + NAREG|NSPECIAL, RESC1, + " lis A1," HA16(AL) COM "load uchar from sname\n" + " lbz A1," LO16(AL) "(A1)\n", }, + +/* load short from memory */ +{ OPLTYPE, INAREG, + SANY, TANY, + SOREG, TSHORT, + NAREG, RESC1, + " lha A1,AL" COM "load short from memory\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SOREG, TUSHORT, + NAREG, RESC1, + " lhz A1,AL" COM "load ushort from memory\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SNAME, TSHORT, + NAREG|NSPECIAL, RESC1, + " lis A1," HA16(AL) COM "load short from sname\n" + " lha A1," LO16(AL) "(A1)\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SNAME, TUSHORT, + NAREG|NSPECIAL, RESC1, + " lis A1," HA16(AL) COM "load ushort from sname\n" + " lhz A1," LO16(AL) "(A1)\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SSCON, TANY, + NAREG, RESC1, + " li A1,AL" COM "load 16-bit constant\n", }, + +{ OPLTYPE, INBREG, + SANY, TANY, + SSCON, TANY, + NBREG, RESC1, + " li A1,AL" COM "load 16-bit constant\n" + " li U1,UL\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SCON, TANY, + NAREG|NASL, RESC1, + " lis A1," HA16(AL) COM "load constant into register\n" + " addi A1,A1," LO16(AL) "\n", }, + +{ OPLTYPE, INBREG, + SANY, TANY, + SCON, TANY, + NBREG, RESC1, + " lis A1," HA16(AL) COM "load constant into register\n" + " addi A1,A1," LO16(AL) "\n" + " lis U1," HA16(UL) "\n" + " addi U1,U1," LO16(UL) "\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SAREG, TANY, + NAREG, RESC1, + " mr A1,AL" COM "load AL into A1\n" }, + +{ OPLTYPE, INBREG, + SANY, TANY, + SBREG, TANY, + NBREG, RESC1, + " mr A1,AL" COM "load UL:AL into U1:A1\n" + " mr U1,UL\n", }, + +{ OPLTYPE, INCREG, + SANY, TANY, + SCREG, TFLOAT|TDOUBLE|TLDOUBLE, + NCREG, RESC1, + " fmr A1,AL" COM "load AL into A1\n", }, + +{ OPLTYPE, INCREG | FEATURE_HARDFLOAT, + SANY, TANY, + SOREG, TFLOAT, + NCREG, RESC1, + " lfs A1,AL" COM "load float\n", }, + +/* soft-float */ +{ OPLTYPE, INAREG, + SANY, TANY, + SOREG, TFLOAT, + NAREG, RESC1, + " lwz A1,AL" COM "load float (soft-float)\n", }, + +{ OPLTYPE, INCREG | FEATURE_HARDFLOAT, + SANY, TANY, + SNAME, TFLOAT, + NCREG|NAREG, RESC2, + " lis A1," HA16(AL) COM "load sname\n" + " lfs A2," LO16(AL) "(A1)\n", }, + +/* soft-float */ +{ OPLTYPE, INAREG, + SANY, TANY, + SNAME, TFLOAT, + NAREG, RESC1, + " lis A1," HA16(AL) COM "load sname (soft-float)\n" + " lwz A1," LO16(AL) "(A1)\n", }, + +{ OPLTYPE, INCREG | FEATURE_HARDFLOAT, + SANY, TANY, + SOREG, TDOUBLE|TLDOUBLE, + NCREG, RESC1, + " lfd A1,AL" COM "load (l)double\n", }, + +/* soft-float */ +{ OPLTYPE, INBREG, + SANY, TANY, + SOREG, TDOUBLE|TLDOUBLE, + NBREG, RESC1, + " lwz A1,AL" COM "load (l)double (soft-float)\n" + " lwz U1,UL\n", }, + +{ OPLTYPE, INCREG | FEATURE_HARDFLOAT, + SANY, TANY, + SNAME, TDOUBLE|TLDOUBLE, + NCREG|NAREG, RESC2, + " lis A1," HA16(AL) COM "load sname\n" + " lfd A2," LO16(AL) "(A1)\n", }, + +{ OPLTYPE, INBREG, + SANY, TANY, + SNAME, TDOUBLE|TLDOUBLE, + NBREG, RESC1, + " lis A1," HA16(AL) COM "load sname (soft-float)\n" + " lwz A1," LO16(AL) "(A1)\n" + " lis U1," HA16(UL) "\n" + " lwz U1," LO16(UL) "(U1)\n", }, + + +/* + * Negate a word. + */ + +{ UMINUS, INAREG, + SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, + SANY, TANY, + NAREG|NASL, RESC1, + " neg A1,AL\n", }, + +{ UMINUS, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SANY, TANY, + NBREG|NBSL, RESC1, + " subfic A1,AL,0\n" + " subfze U1,UL\n", }, + +{ UMINUS, INCREG | FEATURE_HARDFLOAT, + SCREG, TFLOAT|TDOUBLE|TLDOUBLE, + SANY, TANY, + NCREG|NCSL, RESC1, + " fneg A1,AL\n", }, + +{ UMINUS, INAREG, + SAREG, TFLOAT, + SANY, TANY, + NAREG|NASL, RESC1, + " xoris A1,AL,0x8000" COM "(soft-float)\n", }, + +{ UMINUS, INBREG, + SBREG, TDOUBLE|TLDOUBLE, + SANY, TANY, + NBREG|NBSL, RESC1, + " xoris U1,UL,0x8000" COM "(soft-float)\n" + " mr A1,AL\n", }, + +{ COMPL, INAREG, + SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, + SANY, TANY, + NAREG|NASL, RESC1, + " not A1,AL\n", }, + +{ COMPL, INBREG, + SBREG, TLONGLONG|TULONGLONG, + SANY, TANY, + NBREG|NBSL, RESC1, + " not A1,AL\n" + " not U1,UL\n", }, + +/* + * Arguments to functions. + */ + +#if 0 +{ STARG, FOREFF, + SAREG|SOREG|SNAME|SCON, TANY, + SANY, TSTRUCT, + NSPECIAL|NAREG, 0, + "ZF", }, +#endif + +# define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,"" + +{ UMUL, DF( UMUL ), }, + +{ ASSIGN, DF(ASSIGN), }, + +{ STASG, DF(STASG), }, + +{ FLD, DF(FLD), }, + +{ OPLEAF, DF(NAME), }, + +/* { INIT, DF(INIT), }, */ + +{ OPUNARY, DF(UMINUS), }, + +{ OPANY, DF(BITYPE), }, + +{ FREE, FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" }, +}; + +int tablesize = sizeof(table)/sizeof(table[0]); diff --git a/compilers/pcc/pcc-1.0.0/arch/sparc64/CVS/Entries b/compilers/pcc/pcc-1.0.0/arch/sparc64/CVS/Entries new file mode 100644 index 00000000..f7f5d8ce --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/sparc64/CVS/Entries @@ -0,0 +1,7 @@ +/code.c/1.14/Fri Nov 26 17:10:50 2010//Tr-1-0-0-RELEASE +/local.c/1.24/Fri Jan 21 21:47:59 2011//Tr-1-0-0-RELEASE +/local2.c/1.24/Mon Jan 25 03:13:05 2010//Tr-1-0-0-RELEASE +/macdefs.h/1.12/Sat Jan 24 21:43:49 2009//Tr-1-0-0-RELEASE +/order.c/1.6/Fri Oct 30 14:27:29 2009//Tr-1-0-0-RELEASE +/table.c/1.28/Mon Jan 25 03:13:05 2010//Tr-1-0-0-RELEASE +D diff --git a/compilers/pcc/pcc-1.0.0/arch/sparc64/CVS/Repository b/compilers/pcc/pcc-1.0.0/arch/sparc64/CVS/Repository new file mode 100644 index 00000000..3895045e --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/sparc64/CVS/Repository @@ -0,0 +1 @@ +pcc/arch/sparc64 diff --git a/compilers/pcc/pcc-1.0.0/arch/sparc64/CVS/Root b/compilers/pcc/pcc-1.0.0/arch/sparc64/CVS/Root new file mode 100644 index 00000000..71e2ccb9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/sparc64/CVS/Root @@ -0,0 +1 @@ +/cvsroot diff --git a/compilers/pcc/pcc-1.0.0/arch/sparc64/CVS/Tag b/compilers/pcc/pcc-1.0.0/arch/sparc64/CVS/Tag new file mode 100644 index 00000000..060fac05 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/sparc64/CVS/Tag @@ -0,0 +1 @@ +Nr-1-0-0-RELEASE diff --git a/compilers/pcc/pcc-1.0.0/arch/sparc64/code.c b/compilers/pcc/pcc-1.0.0/arch/sparc64/code.c new file mode 100644 index 00000000..043d30f3 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/sparc64/code.c @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2008 David Crawshaw + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "pass1.h" + +void +defloc(struct symtab *sp) +{ + static char *loctbl[] = { "text", "data", "rodata" }; + static int lastloc = -1; + TWORD t; + char *n; + int s; + + if (sp == NULL) + return; + + t = sp->stype; + s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA; + if (s != lastloc) + printf("\n\t.section \".%s\"\n", loctbl[s]); + lastloc = s; + if (s == PROG) + return; + + switch (DEUNSIGN(sp->stype)) { + case CHAR: s = 1; + case SHORT: s = 2; + case INT: + case UNSIGNED: s = 4; + default: s = 8; + } + printf("\t.align %d\n", s); + + n = sp->soname ? sp->soname : sp->sname; + if (sp->sclass == EXTDEF) + printf("\t.global %s\n", n); + if (sp->slevel == 0) { + printf("\t.type %s,#object\n", n); + printf("\t.size %s," CONFMT "\n", n, + tsize(sp->stype, sp->sdf, sp->sap) / SZCHAR); + printf("%s:\n", n); + } else + printf(LABFMT ":\n", sp->soffset); +} + +void +efcode() +{ + /* XXX */ +} + +void +bfcode(struct symtab **sp, int cnt) +{ + int i, off; + NODE *p, *q; + struct symtab *sym; + + /* Process the first six arguments. */ + for (i=0; i < cnt && i < 6; i++) { + sym = sp[i]; + q = block(REG, NIL, NIL, sym->stype, sym->sdf, sym->sap); + q->n_rval = RETREG_PRE(sym->stype) + i; + p = tempnode(0, sym->stype, sym->sdf, sym->sap); + sym->soffset = regno(p); + sym->sflags |= STNODE; + p = buildtree(ASSIGN, p, q); + ecomp(p); + } + + /* Process the remaining arguments. */ + for (off = V9RESERVE; i < cnt; i++) { + sym = sp[i]; + p = tempnode(0, sym->stype, sym->sdf, sym->sap); + off = ALIGN(off, (tlen(p) - 1)); + sym->soffset = off * SZCHAR; + off += tlen(p); + p = buildtree(ASSIGN, p, nametree(sym)); + sym->soffset = regno(p->n_left); + sym->sflags |= STNODE; + ecomp(p); + } +} + +void +bccode() +{ + SETOFF(autooff, SZINT); +} + +void +ejobcode(int flag) +{ +} + +void +bjobcode() +{ +} + +/* + * The first six 64-bit arguments are saved in the registers O0 to O5, + * which become I0 to I5 after the "save" instruction moves the register + * window. Arguments 7 and up must be saved on the stack to %sp+BIAS+176. + * + * For a pretty picture, see Figure 3-16 in the SPARC Compliance Def 2.4. + */ +static NODE * +moveargs(NODE *p, int *regp, int *stacksize) +{ + NODE *r, *q; + + if (p->n_op == CM) { + p->n_left = moveargs(p->n_left, regp, stacksize); + r = p->n_right; + } else { + r = p; + } + + /* XXX more than six FP args can and should be passed in registers. */ + if (*regp > 5 && r->n_op != STARG) { + /* We are storing the stack offset in n_rval. */ + r = block(FUNARG, r, NIL, r->n_type, r->n_df, r->n_ap); + /* Make sure we are appropriately aligned. */ + *stacksize = ALIGN(*stacksize, (tlen(r) - 1)); + r->n_rval = *stacksize; + *stacksize += tlen(r); + } else if (r->n_op == STARG) + cerror("op STARG in moveargs"); + else { + q = block(REG, NIL, NIL, r->n_type, r->n_df, r->n_ap); + + /* + * The first six non-FP arguments go in the registers O0 - O5. + * Float arguments are stored in %fp1, %fp3, ..., %fp29, %fp31. + * Double arguments are stored in %fp0, %fp2, ..., %fp28, %fp30. + * A non-fp argument still increments register, eg. + * test(int a, int b, float b) + * takes %o0, %o1, %fp5. + */ + if (q->n_type == FLOAT) + q->n_rval = F0 + (*regp++ * 2) + 1; + else if (q->n_type == DOUBLE) + q->n_rval = D0 + *regp++; + else if (q->n_type == LDOUBLE) + cerror("long double support incomplete"); + else + q->n_rval = O0 + (*regp)++; + + r = buildtree(ASSIGN, q, r); + } + + if (p->n_op == CM) { + p->n_right = r; + return p; + } + + return r; +} + +NODE * +funcode(NODE *p) +{ + NODE *r, *l; + int reg = 0, stacksize = 0; + + r = l = 0; + + p->n_right = moveargs(p->n_right, ®, &stacksize); + + /* + * This is a particularly gross and inefficient way to handle + * argument overflows. First, we calculate how much stack space + * we need in moveargs(). Then we assign it by moving %sp, make + * the function call, and then move %sp back. + * + * What we should be doing is getting the maximum of all the needed + * stacksize values to the prologue and doing it all in the "save" + * instruction. + */ + if (stacksize != 0) { + stacksize = V9STEP(stacksize); /* 16-bit alignment. */ + + r = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + r->n_lval = 0; + r->n_rval = SP; + r = block(MINUS, r, bcon(stacksize), INT, 0, MKAP(INT)); + + l = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + l->n_lval = 0; + l->n_rval = SP; + r = buildtree(ASSIGN, l, r); + + p = buildtree(COMOP, r, p); + + r = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + r->n_lval = 0; + r->n_rval = SP; + r = block(PLUS, r, bcon(stacksize), INT, 0, MKAP(INT)); + + l = block(REG, NIL, NIL, INT, 0, MKAP(INT)); + l->n_lval = 0; + l->n_rval = SP; + r = buildtree(ASSIGN, l, r); + + p = buildtree(COMOP, p, r); + + } + return p; +} + +int +fldal(unsigned int t) +{ + uerror("illegal field type"); + return ALINT; +} + +void +fldty(struct symtab *p) +{ +} + +int +mygenswitch(int num, TWORD type, struct swents **p, int n) +{ + return 0; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/sparc64/local.c b/compilers/pcc/pcc-1.0.0/arch/sparc64/local.c new file mode 100644 index 00000000..6c3206dc --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/sparc64/local.c @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2008 David Crawshaw + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "pass1.h" + +NODE * +clocal(NODE *p) +{ + struct symtab *sp; + int op; + NODE *r, *l; + + op = p->n_op; + sp = p->n_sp; + l = p->n_left; + r = p->n_right; + +#ifdef PCC_DEBUG + if (xdebug) { + printf("clocal in: %p, %s\n", p, copst(op)); + fwalk(p, eprint, 0); + } +#endif + + switch (op) { + + case NAME: + if (sp->sclass == PARAM || sp->sclass == AUTO) { + /* + * Use a fake structure reference to + * write out frame pointer offsets. + */ + l = block(REG, NIL, NIL, PTR+STRTY, 0, 0); + l->n_lval = 0; + l->n_rval = FP; + r = p; + p = stref(block(STREF, l, r, 0, 0, 0)); + } + break; + case PCONV: /* Remove what PCONVs we can. */ + if (l->n_op == SCONV) + break; + + if (l->n_op == ICON || (ISPTR(p->n_type) && ISPTR(l->n_type))) { + l->n_type = p->n_type; + l->n_qual = p->n_qual; + l->n_df = p->n_df; + l->n_ap = p->n_ap; + nfree(p); + p = l; + } + break; + + case SCONV: + /* Remove redundant conversions. */ + if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 && + btattr[p->n_type].atypsz == btattr[l->n_type].atypsz && + p->n_type != FLOAT && p->n_type != DOUBLE && + l->n_type != FLOAT && l->n_type != DOUBLE && + l->n_type != DOUBLE && p->n_type != LDOUBLE) { + if (l->n_op == NAME || l->n_op == UMUL || + l->n_op == TEMP) { + l->n_type = p->n_type; + nfree(p); + p = l; + break; + } + } + + /* Convert floating point to int before to char or short. */ + if ((l->n_type == FLOAT || l->n_type == DOUBLE || l->n_type == LDOUBLE) + && (DEUNSIGN(p->n_type) == CHAR || DEUNSIGN(p->n_type) == SHORT)) { + p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_ap); + p->n_left->n_type = INT; + break; + } + + /* Transform constants now. */ + if (l->n_op != ICON) + break; + + if (ISPTR(p->n_type)) { + l->n_type = p->n_type; + nfree(p); + p = l; + break; + } + + switch (p->n_type) { + case BOOL: l->n_lval = (l->n_lval != 0); break; + case CHAR: l->n_lval = (char)l->n_lval; break; + case UCHAR: l->n_lval = l->n_lval & 0377; break; + case SHORT: l->n_lval = (short)l->n_lval; break; + case USHORT: l->n_lval = l->n_lval & 0177777; break; + case UNSIGNED: l->n_lval = l->n_lval & 0xffffffff; break; + case INT: l->n_lval = (int)l->n_lval; break; + case ULONG: + case ULONGLONG: l->n_lval = l->n_lval; break; + case LONG: + case LONGLONG: l->n_lval = (long long)l->n_lval; break; + case FLOAT: + case DOUBLE: + case LDOUBLE: + l->n_op = FCON; + l->n_dcon = l->n_lval; + break; + case VOID: + break; + default: + cerror("sconv type unknown %d", p->n_type); + } + + l->n_type = p->n_type; + nfree(p); + p = l; + break; + + case PMCONV: + case PVCONV: + if (r->n_op != ICON) + cerror("converting bad type"); + nfree(p); + p = buildtree(op == PMCONV ? MUL : DIV, l, r); + break; + + case FORCE: + /* Put attached value into the return register. */ + p->n_op = ASSIGN; + p->n_right = p->n_left; + p->n_left = block(REG, NIL, NIL, p->n_type, 0, MKAP(INT)); + p->n_left->n_rval = RETREG_PRE(p->n_type); + break; + } + +#ifdef PCC_DEBUG + if (xdebug) { + printf("clocal out: %p, %s\n", p, copst(op)); + fwalk(p, eprint, 0); + } +#endif + + return p; +} + +void +myp2tree(NODE *p) +{ + struct symtab *sp; + + if (p->n_op != FCON) + return; + + sp = tmpalloc(sizeof(struct symtab)); + sp->sclass = STATIC; + sp->slevel = 1; + sp->soffset = getlab(); + sp->sflags = 0; + sp->stype = p->n_type; + sp->squal = (CON >> TSHIFT); + + defloc(sp); + ninval(0, btattr[p->n_type].atypsz, p); + + p->n_op = NAME; + p->n_lval = 0; + p->n_sp = sp; +} + +int +andable(NODE *p) +{ + return 1; +} + +void +cendarg() +{ + autooff = AUTOINIT; +} + +int +cisreg(TWORD t) +{ + /* SPARCv9 registers are all 64-bits wide. */ + return 1; +} + +NODE * +offcon(OFFSZ off, TWORD t, union dimfun *d, struct attr *ap) +{ + return bcon(off / SZCHAR); +} + +void +spalloc(NODE *t, NODE *p, OFFSZ off) +{ +} + +void +instring(struct symtab *sp) +{ + char *s, *str; + + defloc(sp); + str = sp->sname; + + printf("\t.ascii \""); + for (s = str; *s != 0; ) { + if (*s++ == '\\') + esccon(&s); + if (s - str > 60) { + fwrite(str, 1, s - str, stdout); + printf("\"\n\t.ascii \""); + str = s; + } + } + fwrite(str, 1, s - str, stdout); + printf("\\0\"\n"); +} + +void +zbits(OFFSZ off, int fsz) +{ +} + +void +infld(CONSZ off, int fsz, CONSZ val) +{ +} + +void +ninval(CONSZ off, int fsz, NODE *p) +{ + TWORD t; + struct symtab *sp; + union { float f; double d; int i; long long l; } u; + + t = p->n_type; + sp = p->n_sp; + + if (ISPTR(t)) + t = LONGLONG; + + if (p->n_op != ICON && p->n_op != FCON) + cerror("ninval: not a constant"); + if (p->n_op == ICON && sp != NULL && DEUNSIGN(t) != LONGLONG) + cerror("ninval: not constant"); + + switch (t) { + case CHAR: + case UCHAR: + printf("\t.byte %d\n", (int)p->n_lval & 0xff); + break; + case SHORT: + case USHORT: + printf("\t.half %d\n", (int)p->n_lval &0xffff); + break; + case BOOL: + p->n_lval = (p->n_lval != 0); /* FALLTHROUGH */ + case INT: + case UNSIGNED: + printf("\t.long " CONFMT "\n", p->n_lval); + break; + case LONG: + case ULONG: + case LONGLONG: + case ULONGLONG: + printf("\t.xword %lld", p->n_lval); + if (sp != 0) { + if (sp->sclass == STATIC && sp->slevel > 0) + printf("+" LABFMT, sp->soffset); + else + printf("+%s", sp->soname ? + sp->soname : exname(sp->sname)); + } + printf("\n"); + break; + case FLOAT: + u.f = (float)p->n_dcon; + printf("\t.long %d\n", u.i); + break; + case DOUBLE: + u.d = (double)p->n_dcon; + printf("\t.xword %lld\n", u.l); + break; + } +} + +char * +exname(char *p) +{ + return p ? p : ""; +} + +TWORD +ctype(TWORD type) +{ + return type; +} + +void +calldec(NODE *p, NODE *q) +{ +} + +void +extdec(struct symtab *q) +{ +} + +void +defzero(struct symtab *sp) +{ + int off = (tsize(sp->stype, sp->sdf, sp->sap) + SZCHAR - 1) / SZCHAR; + printf("\t.comm "); + if (sp->slevel == 0) + printf("%s,%d\n", sp->soname ? sp->soname : exname(sp->sname), off); + else + printf(LABFMT ",%d\n", sp->soffset, off); +} + +int +mypragma(char *str) +{ + return 0; +} + +void +fixdef(struct symtab *sp) +{ +} + +void +pass1_lastchance(struct interpass *ip) +{ +} + diff --git a/compilers/pcc/pcc-1.0.0/arch/sparc64/local2.c b/compilers/pcc/pcc-1.0.0/arch/sparc64/local2.c new file mode 100644 index 00000000..85674ff0 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/sparc64/local2.c @@ -0,0 +1,425 @@ +/* + * Copyright (c) 2008 David Crawshaw + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "pass1.h" +#include "pass2.h" + + +char * +rnames[] = { + /* "\%g0", always zero, removed due to 31-element class limit */ + "\%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", + + "\%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" XXX removed due to 31-element class limit */ + + "\%f0", "\%f2", "\%f4", "\%f6", "\%f8", "\%f10", "\%f12", "\%f14", + "\%f16", "\%f18", "\%f20", "\%f22", "\%f24", "\%f26", "\%f28", "\%f30", + + "\%sp", "\%fp", +}; + +void +deflab(int label) +{ + printf(LABFMT ":\n", label); +} + +void +prologue(struct interpass_prolog *ipp) +{ + int i, stack; + + stack = V9RESERVE + V9STEP(p2maxautooff); + + for (i = ipp->ipp_regs[0]; i; i >>= 1) + if (i & 1) + stack += 16; + + /* TODO printf("\t.proc %d\n"); */ + if (ipp->ipp_vis) + printf("\t.global %s\n", ipp->ipp_name); + printf("\t.align 4\n"); + printf("%s:\n", ipp->ipp_name); + if (SIMM13(stack)) + printf("\tsave %%sp,-%d,%%sp\n", stack); + else { + printf("\tsetx -%d,%%g4,%%g1\n", stack); + printf("\tsave %%sp,%%g1,%%sp\n"); + } +} + +void +eoftn(struct interpass_prolog *ipp) +{ + printf("\tret\n"); + printf("\trestore\n"); + printf("\t.type %s,#function\n", ipp->ipp_name); + printf("\t.size %s,(.-%s)\n", ipp->ipp_name, ipp->ipp_name); +} + +void +hopcode(int f, int o) +{ + char *str; + + switch (o) { + case EQ: str = "brz"; break; + case NE: str = "brnz"; break; + case ULE: + case LE: str = "brlez"; break; + case ULT: + case LT: str = "brlz"; break; + case UGE: + case GE: str = "brgez"; break; + case UGT: + case GT: str = "brgz"; break; + case PLUS: str = "add"; break; + case MINUS: str = "sub"; break; + case AND: str = "and"; break; + case OR: str = "or"; break; + case ER: str = "xor"; break; + default: + comperr("unknown hopcode: %d (with %c)", o, f); + return; + } + + printf("%s%c", str, f); +} + +int +tlen(NODE *p) +{ + switch (p->n_type) { + case CHAR: + case UCHAR: + return 1; + case SHORT: + case USHORT: + return (SZSHORT / SZCHAR); + case FLOAT: + return (SZFLOAT / SZCHAR); + case DOUBLE: + return (SZDOUBLE / SZCHAR); + case INT: + case UNSIGNED: + return (SZINT / SZCHAR); + case LONG: + case ULONG: + case LONGLONG: + case ULONGLONG: + return SZLONGLONG / SZCHAR; + default: + if (!ISPTR(p->n_type)) + comperr("tlen type unknown: %d"); + return SZPOINT(p->n_type) / SZCHAR; + } +} + +void +zzzcode(NODE * p, int c) +{ + char *str; + NODE *l, *r; + l = p->n_left; + r = p->n_right; + + switch (c) { + + case 'A': /* Add const. */ + if (ISPTR(l->n_type) && l->n_rval == FP) + r->n_lval += V9BIAS; + + if (SIMM13(r->n_lval)) + expand(p, 0, "\tadd AL,AR,A1\t\t! add const\n"); + else + expand(p, 0, "\tsetx AR,A3,A2\t\t! add const\n" + "\tadd AL,A2,A1\n"); + break; + case 'B': /* Subtract const. */ + if (ISPTR(l->n_type) && l->n_rval == FP) + r->n_lval -= V9BIAS; + + if (SIMM13(r->n_lval)) + expand(p, 0, "\tsub AL,AR,A1\t\t! subtract const\n"); + else + expand(p, 0, "\tsetx AR,A3,A2\t\t! subtract const\n" + "\tsub AL,A2,A1\n"); + break; + case 'C': /* Load constant to register. */ + if (ISPTR(p->n_type)) + expand(p, 0, + "\tsethi %h44(AL),A1\t\t! load label\n" + "\tor A1,%m44(AL),A1\n" + "\tsllx A1,12,A1\n" + "\tor A1,%l44(AL),A1\n"); + else if (SIMM13(p->n_lval)) + expand(p, 0, "\tor %g0,AL,A1\t\t\t! load const\n"); + else + expand(p, 0, "\tsetx AL,A2,A1\t\t! load const\n"); + break; + case 'F': /* Floating-point comparison, cf. hopcode(). */ + switch (p->n_op) { + case EQ: str = "fbe"; break; + case NE: str = "fbne"; break; + case ULE: + case LE: str = "fbule"; break; + case ULT: + case LT: str = "fbul"; break; + case UGE: + case GE: str = "fbuge"; break; + case UGT: + case GT: str = "fbug"; break; + /* XXX + case PLUS: str = "add"; break; + case MINUS: str = "sub"; break; + case AND: str = "and"; break; + case OR: str = "or"; break; + case ER: str = "xor"; break;*/ + default: + comperr("unknown float code: %d", p->n_op); + return; + } + printf(str); + break; + + case 'Q': /* Structure assignment. */ + /* TODO Check if p->n_stsize is small and use a few ldx's + to move the struct instead of memcpy. The equiv. + could be done on all the architectures. */ + if (l->n_rval != O0) + printf("\tmov %s,%s\n", rnames[l->n_rval], rnames[O0]); + if (SIMM13(p->n_stsize)) + printf("\tor %%g0,%d,%%o2\n", p->n_stsize); + else + printf("\tsetx %d,%%g1,%%o2\n", p->n_stsize); + printf("\tcall memcpy\t\t\t! struct assign (dest, src, len)\n"); + printf("\tnop\n"); + break; + default: + cerror("unknown zzzcode call: %c", c); + } +} + +int +rewfld(NODE * p) +{ + return (1); +} + +int +fldexpand(NODE *p, int cookie, char **cp) +{ + printf("XXX fldexpand called\n"); /* XXX */ + return 1; +} + +int +flshape(NODE * p) +{ + return SRREG; +} + +int +shtemp(NODE * p) +{ + return 0; +} + + +void +adrcon(CONSZ val) +{ +} + +void +conput(FILE * fp, NODE * p) +{ + if (p->n_op != ICON) { + comperr("conput got bad op: %s", copst(p->n_op)); + return; + } + + if (p->n_name[0] != '\0') { + fprintf(fp, "%s", p->n_name); + if (p->n_lval > 0) + fprintf(fp, "+"); + if (p->n_lval) + fprintf(fp, CONFMT, p->n_lval); + } else + fprintf(fp, CONFMT, p->n_lval); +} + +void +insput(NODE * p) +{ + comperr("insput"); +} + +void +upput(NODE *p, int size) +{ + comperr("upput"); +} + +void +adrput(FILE * io, NODE * p) +{ + int64_t off; + + if (p->n_op == FLD) { + printf("adrput a FLD\n"); + p = p->n_left; + } + + if (p->n_op == UMUL && p->n_right == 0) + p = p->n_left; + + off = p->n_lval; + + switch (p->n_op) { + case NAME: + if (p->n_name[0] != '\0') + fputs(p->n_name, io); + if (off > 0) + fprintf(io, "+"); + if (off != 0) + fprintf(io, CONFMT, (long long int)off); + return; + case OREG: + fprintf(io, "%s", rnames[p->n_rval]); + if (p->n_rval == FP) + off += V9BIAS; + if (p->n_rval == SP) + off += V9BIAS + V9RESERVE; + if (off > 0) + fprintf(io, "+"); + if (off) + fprintf(io, CONFMT, (CONSZ)off); + return; + case ICON: + /* addressable value of the constant */ + conput(io, p); + return; + case REG: + fputs(rnames[p->n_rval], io); + return; + case FUNARG: + /* We do something odd and store the stack offset in n_rval. */ + fprintf(io, "%d", V9BIAS + V9RESERVE + p->n_rval); + return; + default: + comperr("bad address, %s, node %p", copst(p->n_op), p); + return; + } +} + +void +cbgen(int o, int lab) +{ +} + +void +myreader(struct interpass * ipole) +{ +} + +void +mycanon(NODE * p) +{ +} + +void +myoptim(struct interpass * ipole) +{ +} + +void +rmove(int s, int d, TWORD t) +{ + printf("\t"); + + if (t == FLOAT) printf("fmovs"); + else if (t == DOUBLE) printf("fmovd"); + else printf("mov"); + + printf(" %s,%s\t\t\t! rmove()\n", rnames[s], rnames[d]); +} + +int +gclass(TWORD t) +{ + if (t == FLOAT) + return CLASSB; + if (t == DOUBLE) + return CLASSC; + return CLASSA; +} + +void +lastcall(NODE *p) +{ +} + +int +special(NODE *p, int shape) +{ + return SRNOPE; +} + +void mflags(char *str) +{ +} + +int +COLORMAP(int c, int *r) +{ + int num=0; + + switch (c) { + case CLASSA: + num += r[CLASSA]; + return num < 32; + case CLASSB: + num += r[CLASSB]; + num += 2*r[CLASSC]; + return num < 32;; + case CLASSC: + num += r[CLASSC]; + num += 2*r[CLASSB]; + return num < 17; + case CLASSD: + return 0; + default: + comperr("COLORMAP: unknown class: %d", c); + return 0; + } +} +/* + * Do something target-dependent for xasm arguments. + * Supposed to find target-specific constraints and rewrite them. + */ +int +myxasm(struct interpass *ip, NODE *p) +{ + return 0; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/sparc64/macdefs.h b/compilers/pcc/pcc-1.0.0/arch/sparc64/macdefs.h new file mode 100644 index 00000000..5d0ec81d --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/sparc64/macdefs.h @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2008 David Crawshaw + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +/* + * Many arithmetic instructions take 'reg_or_imm' in SPARCv9, where imm + * means we can use a signed 13-bit constant (simm13). This gives us a + * shortcut for small constants, instead of loading them into a register. + * Special handling is required because 13 bits lies between SSCON and SCON. + */ +#define SIMM13(val) (val < 4096 && val > -4097) + +/* + * The SPARCv9 ABI specifies a stack bias of 2047 bits. This means that the + * end of our call space is %fp+V9BIAS, working back towards %sp+V9BIAS+176. + */ +#define V9BIAS 2047 + +/* + * The ABI requires that every frame reserve 176 bits for saving registers + * in the case of a spill. The stack size must be 16-bit aligned. + */ +#define V9RESERVE 176 +#define V9STEP(x) ALIGN(x, 0xf) +#define ALIGN(x, y) ((x & y) ? (x + y) & ~y : x) + + +#define makecc(val,i) lastcon = (lastcon<<8)|((val<<24)>>24); + +#define ARGINIT (7*8) /* XXX */ +#define AUTOINIT (0) + +/* Type sizes */ +#define SZCHAR 8 +#define SZBOOL 32 +#define SZINT 32 +#define SZFLOAT 32 +#define SZDOUBLE 64 +#define SZLDOUBLE 64 +#define SZLONG 64 +#define SZSHORT 16 +#define SZLONGLONG 64 +#define SZPOINT(t) 64 + +/* Type alignments */ +#define ALCHAR 8 +#define ALBOOL 32 +#define ALINT 32 +#define ALFLOAT 32 +#define ALDOUBLE 64 +#define ALLDOUBLE 64 +#define ALLONG 64 +#define ALLONGLONG 64 +#define ALSHORT 16 +#define ALPOINT 64 +#define ALSTRUCT 32 +#define ALSTACK 64 + +/* Min/max values. */ +#define MIN_CHAR -128 +#define MAX_CHAR 127 +#define MAX_UCHAR 255 +#define MIN_SHORT -32768 +#define MAX_SHORT 32767 +#define MAX_USHORT 65535 +#define MIN_INT -1 +#define MAX_INT 0x7fffffff +#define MAX_UNSIGNED 0xffffffff +#define MIN_LONGLONG 0x8000000000000000LL +#define MAX_LONGLONG 0x7fffffffffffffffLL +#define MAX_ULONGLONG 0xffffffffffffffffULL +#define MIN_LONG MIN_LONGLONG +#define MAX_LONG MAX_LONGLONG +#define MAX_ULONG MAX_ULONGLONG + +#define BOOL_TYPE INT + +typedef long long CONSZ; +typedef unsigned long long U_CONSZ; +typedef long long OFFSZ; + +#define CONFMT "%lld" +#define LABFMT "L%d" +#define STABLBL "LL%d" + +#define BACKAUTO /* Stack grows negatively for automatics. */ +#define BACKTEMP /* Stack grows negatively for temporaries. */ + +#undef FIELDOPS +#define RTOLBYTES + +#define ENUMSIZE(high,low) INT +#define BYTEOFF(x) ((x)&03) +#define BITOOR(x) (x) + +#define szty(t) ((ISPTR(t) || (t) == DOUBLE || \ + (t) == LONG || (t) == ULONG || \ + (t) == LONGLONG || (t) == ULONGLONG) ? 2 : 1) + + +/* Register names. */ + +#define MAXREGS (31 + 31 + 16 + 2) +#define NUMCLASS 4 + +//define G0 -1 +#define G1 0 +#define G2 1 +#define G3 2 +#define G4 3 +#define G5 4 +#define G6 5 +#define G7 6 +#define O0 7 +#define O1 8 +#define O2 9 +#define O3 10 +#define O4 11 +#define O5 12 +#define O6 13 +#define O7 14 +#define L0 15 +#define L1 16 +#define L2 17 +#define L3 18 +#define L4 19 +#define L5 20 +#define L6 21 +#define L7 22 +#define I0 23 +#define I1 24 +#define I2 25 +#define I3 26 +#define I4 27 +#define I5 28 +#define I6 29 +#define I7 30 + +#define F0 31 +#define F1 32 +#define F2 33 +#define F3 34 +#define F4 35 +#define F5 36 +#define F6 37 +#define F7 38 +#define F8 39 +#define F9 40 +#define F10 41 +#define F11 42 +#define F12 43 +#define F13 44 +#define F14 45 +#define F15 46 +#define F16 47 +#define F17 48 +#define F18 49 +#define F19 50 +#define F20 51 +#define F21 52 +#define F22 53 +#define F23 54 +#define F24 55 +#define F25 56 +#define F26 57 +#define F27 58 +#define F28 59 +#define F29 60 +#define F30 61 +//define F31 XXX +#define D0 62 +#define D1 63 +#define D2 64 +#define D3 65 +#define D4 66 +#define D5 67 +#define D6 68 +#define D7 69 +#define D8 70 +#define D9 71 +#define D10 72 +#define D11 73 +#define D12 74 +#define D13 75 +#define D14 76 +#define D15 77 + +#define SP 78 +#define FP 79 + +#define FPREG FP + +#define RETREG(x) ((x)==DOUBLE ? D0 : (x)==FLOAT ? F1 : O0) +#define RETREG_PRE(x) ((x)==DOUBLE ? D0 : (x)==FLOAT ? F1 : I0) + +#define RSTATUS \ + /* global */ \ + SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, \ + SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, \ + /* out */ \ + SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \ + SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \ + /* local */ \ + SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \ + SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \ + /* in */ \ + SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \ + SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \ + /* 32-bit floating point */ \ + SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \ + SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \ + SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \ + SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, /*, SBREG */ \ + /* 64-bit floating point */ \ + SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \ + SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \ + /* sp */ SDREG, \ + /* fp */ SDREG + +#define ROVERLAP \ + { -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 }, \ +/* 32-bit floating point */ \ + { D0, -1 }, { D0, -1 }, { D1, -1 }, { D1, -1 }, \ + { D2, -1 }, { D2, -1 }, { D3, -1 }, { D3, -1 }, \ + { D4, -1 }, { D4, -1 }, { D5, -1 }, { D5, -1 }, \ + { D6, -1 }, { D6, -1 }, { D7, -1 }, { D7, -1 }, \ + { D8, -1 }, { D8, -1 }, { D9, -1 }, { D9, -1 }, \ + { D10, -1 }, { D10, -1 }, { D11, -1 }, { D11, -1 }, \ + { D12, -1 }, { D12, -1 }, { D13, -1 }, { D13, -1 }, \ + { D14, -1 }, { D14, -1 }, { D15, -1 }, /* { D15, -1 }, */ \ +/* 64-bit floating point */ \ + { F0, F1, -1 }, { F2, F3, -1 }, { F4, F5, -1 }, \ + { F6, F7, -1 }, { F8, F9, -1 }, { F10, F11, -1 }, \ + { F12, F13, -1 }, { F14, F15, -1 }, { F16, F17, -1 }, \ + { F18, F19, -1 }, { F20, F21, -1 }, { F22, F23, -1 }, \ + { F24, F25, -1 }, { F26, F27, -1 }, { F28, F29, -1 }, \ + { F30, /* F31, */ -1 }, \ + { -1 }, \ + { -1 } + +#define GCLASS(x) (x <= I7 ? CLASSA : \ + (x <= F30 ? CLASSB : \ + (x <= D15 ? CLASSC : \ + (x == SP || x == FP ? CLASSD : 0)))) +#define PCLASS(p) (1 << gclass((p)->n_type)) +#define DECRA(x,y) (((x) >> (y*7)) & 127) +#define ENCRA(x,y) ((x) << (7+y*7)) +#define ENCRD(x) (x) + +int COLORMAP(int c, int *r); diff --git a/compilers/pcc/pcc-1.0.0/arch/sparc64/order.c b/compilers/pcc/pcc-1.0.0/arch/sparc64/order.c new file mode 100644 index 00000000..8c683810 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/sparc64/order.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2008 David Crawshaw + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "pass2.h" + +/* is it legal to make an OREG or NAME entry which has an + * offset of off, (from a register of r), if the + * resulting thing had type t */ +int +notoff(TWORD t, int r, CONSZ off, char *cp) +{ + return !SIMM13(off); +} + +/* + * Turn a UMUL-referenced node into OREG. + */ +void +offstar(NODE *p, int shape) +{ + if (x2debug) + printf("offstar(%p)\n", p); + + if (p->n_op == PLUS || p->n_op == MINUS) { + if (p->n_right->n_op == ICON && SIMM13(p->n_right->n_lval)) { + if (isreg(p->n_left) == 0) + (void)geninsn(p->n_left, INAREG); + /* Converted in ormake() */ + return; + } + } + (void)geninsn(p, INAREG); +} + +void +myormake(NODE *q) +{ +} + +int +shumul(NODE *p, int shape) +{ + if (shape & SOREG) + return SROREG; + return SRNOPE; +} + +int +setbin(NODE *p) +{ + return 0; +} + +int +setasg(NODE *p, int cookie) +{ + return 0; +} + +int +setuni(NODE *p, int cookie) +{ + return 0; +} + +struct rspecial * +nspecial(struct optab *q) +{ + switch (q->op) { + case STASG: { + static struct rspecial s[] = { + { NEVER, O0 }, + { NRIGHT, O1 }, + { NEVER, O2 }, + { 0 } + }; + return s; + } + } + + comperr("unknown nspecial %d: %s", q - table, q->cstring); + return 0; /* XXX */ +} + +int +setorder(NODE *p) +{ + return 0; +} + +int * +livecall(NODE *p) +{ + static int ret[] = { O0, O1, O2, O3, O4, O5, O6, O7, -1 }; + return ret; +} + +int +acceptable(struct optab *op) +{ + return 1; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/sparc64/table.c b/compilers/pcc/pcc-1.0.0/arch/sparc64/table.c new file mode 100644 index 00000000..674a1899 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/sparc64/table.c @@ -0,0 +1,963 @@ +/* + * Copyright (c) 2008 David Crawshaw + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "pass2.h" + +#define TS64 TLONG|TLONGLONG +#define TU64 TULONG|TULONGLONG|TPOINT +#define T64 TS64|TU64 + +struct optab table[] = { + +{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", }, /* empty */ + +{ PCONV, INAREG, + SAREG, T64|TINT, + SAREG, T64, + 0, RLEFT, + " ! convert between word and pointer\n", }, + +/* Conversions. */ + +{ SCONV, INAREG, + SAREG, T64|TUNSIGNED, + SAREG, TINT, + NAREG|NASL, RESC1, + " sra AL,0,A1 \t\t! (u)int64/32 -> (u)int32\n", }, + +{ SCONV, INAREG, + SAREG, T64|TINT|TUNSIGNED, + SAREG, TSHORT, + NAREG|NASL, RESC1, + " sll AL,16,A1 \t\t! (u)int64/32 -> int16\n" + " sra AL,16,A1\n" + " sra AL, 0,A1\n", }, + +{ SCONV, INAREG, + SAREG, T64|TINT|TUNSIGNED, + SAREG, TUSHORT, + NAREG|NASL, RESC1, + " sll AL,16,A1 \t\t! (u)int64/32 -> uint16\n" + " srl AL,16,A1\n", }, + +{ SCONV, INAREG, + SAREG, T64|TINT|TUNSIGNED|TSHORT|TUSHORT, + SAREG, TCHAR, + NAREG|NASL, RESC1, + " sll AL,24,A1 \t\t! (u)int64/32/16 -> int8\n" + " sra AL,24,A1\n" + " sra AL, 0,A1\n", }, + +{ SCONV, INAREG, + SAREG, T64|TINT|TUNSIGNED|TSHORT|TUSHORT, + SAREG, TUCHAR, + NAREG|NASL, RESC1, + " and AL,0xff,A1 \t\t! (u)int64/32/16 -> uint8\n", }, + +{ SCONV, INAREG, + SAREG, T64|TINT|TUNSIGNED|TSHORT|TUSHORT|TCHAR|TUCHAR, /* TCHAR|TUCHAR added to handle char -> long (among others) */ + SAREG, T64, + 0, RLEFT, + " \t\t! (u)int64...8 -> (u)int64\n", }, + +{ SCONV, INAREG, + SAREG, TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG, TINT, + 0, RLEFT, + " \t\t! (u)int16/8 -> int32\n", }, + +{ SCONV, INAREG, + SAREG, T64|TINT|TSHORT|TCHAR, + SAREG, TUNSIGNED, + 0, RLEFT, + " srl AL, 0,A1 \t\t! int32/16/8 -> uint32\n", }, + +{ SCONV, INAREG, + SAREG, TUSHORT|TUCHAR, + SAREG, TUNSIGNED, + 0, RLEFT, + " \t\t! uint16/8 -> uint32\n", }, + +{ SCONV, INBREG, + SBREG, TINT|TUNSIGNED, + SBREG, TFLOAT, + NBREG|NASL, RESC1, + " fitos AL,A1 \t\t! (u)int32 -> float\n", }, + +{ SCONV, INBREG, + SBREG, T64, + SBREG, TFLOAT, + NBREG|NASL, RESC1, + " fxtos AL,A1 \t\t! (u)int64 -> float\n", }, + +{ SCONV, INCREG, + SCREG, TINT|TUNSIGNED, + SCREG, TDOUBLE, + NCREG|NASL, RESC1, + " fitod AL,A1 \t\t! (u)int32 -> double\n", }, + +{ SCONV, INCREG, + SCREG, T64, + SCREG, TDOUBLE, + NCREG|NASL, RESC1, + " fxtod AL,A1 \t\t! (u)int64 -> double\n", }, + + +/* Floating-point conversions must be stored and loaded. */ + +{ SCONV, INAREG, + SOREG, TFLOAT, + SAREG, TINT, + NAREG|(2*NBREG), RESC1, + " ld [AL],A2 \t\t! float -> int32\n" + " nop\n" + " fmovs A2,A3\n" + " fstoi A2,A2\n" + " st A2,[AL]\n" + " nop\n" + " ld [AL],A1\n" + " nop\n" + " st A3,[AL]\n" + " nop\n", }, + +{ SCONV, INAREG, + SOREG, TDOUBLE, + SAREG, TINT, + NAREG|(2*NCREG), RESC1, + " ld [AL],A2 \t\t! double -> int32\n" + " nop\n" + " fmovd A2,A3\n" + " fdtoi A2,A2\n" + " std A2,[AL]\n" + " nop\n" + " ldd [AL],A1\n" + " nop\n" + " std A3,[AL]\n" + " nop\n", }, + +{ SCONV, INBREG, + SOREG, T64|TUNSIGNED, + SBREG, TFLOAT, + NBREG, RESC1, + " ld [AL],A1 \t\t! int64 -> float\n" + " fxtos A1,A1\n", }, + +{ SCONV, INBREG, + SOREG, TINT|TSHORT|TCHAR, + SBREG, TFLOAT, + NBREG, RESC1, + " ld [AL],A1 \t\t! int32/16/8 -> float\n" + " fitos A1,A1\n", }, // XXX need 'lds', 'ldh', etc + +{ SCONV, INCREG, + SOREG, T64|TUNSIGNED, + SCREG, TDOUBLE, + NCREG, RESC1, + " ldd [AL],A1 \t\t! (u)int64 -> double\n" + " fxtod A1,A1\n", }, + +{ SCONV, INCREG, + SOREG, TINT|TSHORT|TCHAR, + SCREG, TDOUBLE, + NCREG, RESC1, + " ld [AL],A1 \t\t! int32/16/8 -> double\n" + " fitod A1,A1\n", }, // XXX need 'lds' 'ldh' 'ld', etc. + +{ SCONV, INBREG, + SCREG, TDOUBLE, + SBREG, TFLOAT, + NBREG, RESC1, + " fdtos AL,A1 \t\t! double -> float\n",}, + +{ SCONV, INCREG, + SBREG, TFLOAT, + SCREG, TDOUBLE, + NCREG, RESC1, + " fstod AL,A1 \t\t! float -> double\n",}, + +{ SCONV, INAREG, + SBREG, TFLOAT, + SAREG, TINT, + NAREG|NBREG, RESC1, + " fstoi AL,A2 \t\t! float -> int\n" + " st A2,[%fp+2047]\n" + " nop\n" + " ld [%fp+2047],A1\n" + " nop\n",}, + +{ SCONV, INAREG, + SCREG, TDOUBLE, + SAREG, TINT, + NAREG|NCREG, RESC1, + " fdtoi AL,A2 \t\t! double -> int\n" + " st A2,[%fp+2047]\n" + " nop\n" + " ld [%fp+2047],A1\n" + " nop\n",}, + + +/* Multiplication and division */ + +{ MUL, INAREG, + SAREG, TANY, + SAREG, TANY, + NAREG|NASR|NASL, RESC1, + " mulx AL,AR,A1 ! multiply\n", }, + +{ MUL, INBREG, + SBREG, TFLOAT, + SBREG, TFLOAT, + NBREG|NBSR|NBSL, RESC1, + " fmuls AL,AR,A1 ! multiply float\n", }, + +{ MUL, INCREG, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG|NCSR|NCSL, RESC1, + " fmuld AL,AR,A1 ! multiply double\n", }, + +{ DIV, INAREG, + SAREG, TUNSIGNED|TUSHORT|TUCHAR|TU64, + SAREG, TUNSIGNED|TUSHORT|TUCHAR|TU64, + NAREG|NASR|NASL, RESC1, + " udivx AL,AR,A1 ! unsigned division\n", }, + +{ DIV, INAREG, + SAREG, TINT|TSHORT|TCHAR|TS64, + SAREG, TINT|TSHORT|TCHAR|TS64, + NAREG|NASR|NASL, RESC1, + " sdivx AL,AR,A1 ! signed division\n", }, + +{ DIV, INBREG, + SBREG, TFLOAT, + SBREG, TFLOAT, + NBREG|NBSR|NBSL, RESC1, + " fdivs AL,AR,A1 ! divide float\n", }, + +{ DIV, INCREG, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG|NCSR|NCSL, RESC1, + " fdivd AL,AR,A1 ! divide double\n", }, + +{ MOD, INAREG, + SAREG, TUNSIGNED|TUSHORT|TUCHAR|TU64, + SAREG, TUNSIGNED|TUSHORT|TUCHAR|TU64, + NAREG, RESC1, + " udivx AL,AR,A1 ! unsigned modulo\n" + " mulx A1,AR,A1\n" + " sub AL,A1,A1\n", }, + +{ MOD, INAREG, + SAREG, TINT|TSHORT|TCHAR|TS64, + SAREG, TINT|TSHORT|TCHAR|TS64, + NAREG, RESC1, + " sdivx AL,AR,A1 ! signed modulo\n" + " mulx A1,AR,A1\n" + " sub AL,A1,A1\n", }, + +{ PLUS, INAREG, + SAREG, TANY, + SAREG, TANY, + NAREG|NASL, RESC1, + " add AL,AR,A1\n", }, + +{ PLUS, INBREG, + SBREG, TFLOAT, + SBREG, TFLOAT, + NBREG|NBSL, RESC1, + " fadds AL,AR,A1\n", }, + +{ PLUS, INCREG, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG|NCSL, RESC1, + " faddd AL,AR,A1\n", }, + +{ PLUS, INAREG, + SAREG, TANY, + SCON, TANY, + (3*NAREG), RESC1, + "ZA", }, + +{ MINUS, INAREG, + SAREG, TANY, + SAREG, TANY, + NAREG|NASL, RESC1, + " sub AL,AR,A1\n", }, + +{ MINUS, INBREG, + SBREG, TANY, + SBREG, TANY, + NBREG|NBSL|NBSR, RESC1, + " fsubs AL,AR,A1\n", }, + +{ MINUS, INCREG, + SCREG, TANY, + SCREG, TANY, + NCREG|NCSL|NBSR, RESC1, + " fsubd AL,AR,A1\n", }, + +{ MINUS, INAREG, + SAREG, TANY, + SCON, TANY, + (3*NAREG), RESC1, + "ZB", }, + +{ UMINUS, INAREG, + SAREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1, + " sub %g0,AL,A1\n", }, + +{ UMINUS, INBREG, + SBREG, TANY, + SANY, TANY, + NBREG|NBSL, RESC1, + " fsubs %g0,AL,A1\n", }, + +{ UMINUS, INCREG, + SCREG, TANY, + SANY, TANY, + NCREG|NCSL, RESC1, + " fsubd %g0,AL,A1\n", }, + +/* Shifts */ + +{ RS, INAREG, + SAREG, TINT|TUNSIGNED|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG|SCON, TINT|TUNSIGNED|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " srl AL,AR,A1 ! shift right\n", }, + +{ RS, INAREG, + SAREG, T64, + SAREG|SCON, T64|TINT|TUNSIGNED|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " srlx AL,AR,A1 ! shift right\n", }, + +{ LS, INAREG, + SAREG, TINT|TUNSIGNED|TSHORT|TUSHORT|TCHAR|TUCHAR, + SAREG|SCON, TINT|TUNSIGNED|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " sll AL,AR,A1 ! shift left\n", }, + +{ LS, INAREG, + SAREG, T64, + SAREG|SCON, TINT|TUNSIGNED|TSHORT|TUSHORT|TCHAR|TUCHAR, + NAREG|NASL, RESC1, + " sllx AL,AR,A1 ! shift left\n", }, + +{ COMPL, INAREG, + SAREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1, + " not AL,A1 ! complement\n", }, + +/* Assignments */ + +{ ASSIGN, FOREFF|INAREG, /* FIXME: Remove [,] here and add them in adrput instead. */ + SAREG|SOREG, TINT|TUNSIGNED, + SAREG, TINT|TUNSIGNED, + 0, RDEST, + " stw AR,[AL] ! store (u)int32\n" + " nop\n", }, + +{ ASSIGN, FOREFF|INAREG, + SOREG, TSHORT|TUSHORT, + SAREG, TSHORT|TUSHORT, + 0, RDEST, + " sth AR,[AL] ! store (u)int16\n" + " nop\n", }, + +{ ASSIGN, FOREFF|INAREG, + SOREG, TCHAR|TUCHAR, + SAREG, TCHAR|TUCHAR, + 0, RDEST, + " stb AR,[AL] ! store (u)int8\n" + " nop\n", }, + +{ ASSIGN, FOREFF|INAREG, + SOREG, T64, + SAREG, T64, + 0, RDEST, + " stx AR,[AL] ! store (u)int64\n" + " nop\n", }, + +{ ASSIGN, FOREFF|INBREG, + SOREG, TFLOAT, + SBREG, TFLOAT, + 0, RDEST, + " st AR,[AL] ! store float\n" + " nop\n", }, + +{ ASSIGN, FOREFF|INBREG, + SOREG, TINT, + SBREG, TINT, + 0, RDEST, + " st AR,[AL] ! store int from fp address\n" + " nop\n", }, + +{ ASSIGN, FOREFF|INCREG, + SOREG, TDOUBLE, + SCREG, TDOUBLE, + 0, RDEST, + " std AR,[AL] ! store double\n" + " nop\n", }, + +{ ASSIGN, FOREFF|INCREG, + SOREG, TINT, + SCREG, TINT, + 0, RDEST, + " st AR,[AL] ! store int from fp address\n" + " nop\n", }, + + +{ ASSIGN, FOREFF|INAREG, + SNAME, TINT|TUNSIGNED, + SAREG, TINT|TUNSIGNED, + NAREG, RDEST, + " sethi %h44(AL),A1 \t! store (u)int32 into sname\n" + " or A1,%m44(AL),A1\n" + " sllx A1,12,A1\n" + " stw AR,[A1+%l44(AL)]\n" + " nop\n", }, + +{ ASSIGN, FOREFF|INAREG, + SNAME, TSHORT|TUSHORT, + SAREG, TSHORT|TUSHORT, + NAREG, RDEST, + " sethi %h44(AL),A1 \t! store (u)int16 into sname\n" + " or A1,%m44(AL),A1\n" + " sllx A1,12,A1\n" + " sth AR,[A1+%l44(AL)]\n" + " nop\n", }, + +{ ASSIGN, FOREFF|INAREG, + SNAME, TCHAR|TUCHAR, + SAREG, TCHAR|TUCHAR, + NAREG, RDEST, + " sethi %h44(AL),A1 \t! store (u)int8 into sname\n" + " or A1,%m44(AL),A1\n" + " sllx A1,12,A1\n" + " stb AR,[A1+%l44(AL)]\n" + " nop\n", }, + +{ ASSIGN, FOREFF|INAREG, + SNAME, T64, + SAREG, T64, + NAREG, RDEST, + " sethi %h44(AL),A1 \t! store (u)int64 into sname\n" + " or A1,%m44(AL),A1\n" + " sllx A1,12,A1\n" + " stx AR,[A1+%l44(AL)]\n" + " nop\n", }, + +{ ASSIGN, FOREFF|INBREG, + SNAME, TFLOAT|TINT, + SBREG, TFLOAT|TINT, + NAREG, RDEST, + " sethi %h44(AL),A1 \t! store float into sname\n" + " or A1,%m44(AL),A1\n" + " sllx A1,12,A1\n" + " st AR,[A1+%l44(AL)]\n" + " nop\n", }, + +{ ASSIGN, FOREFF|INCREG, + SNAME, TDOUBLE, + SCREG, TDOUBLE, + NAREG, RDEST, + " sethi %h44(AL),A1 \t! store double into sname\n" + " or A1,%m44(AL),A1\n" + " sllx A1,12,A1\n" + " std AR,[A1+%l44(AL)]\n" + " nop\n", }, + +{ ASSIGN, FOREFF|INCREG, + SNAME, TINT, + SCREG, TINT, + NAREG, RDEST, + " sethi %h44(AL),A1 \t! store int into sname\n" + " or A1,%m44(AL),A1\n" + " sllx A1,12,A1\n" + " st AR,[A1+%l44(AL)]\n" + " nop\n", }, + +{ ASSIGN, FOREFF|INAREG, + SAREG, TANY, + SAREG, TANY, + 0, RDEST, + " mov AR,AL ! register move\n", }, + +{ ASSIGN, FOREFF|INBREG, + SBREG, TANY, + SBREG, TANY, + 0, RDEST, + " fmovs AR,AL ! move float\n", }, + +{ ASSIGN, FOREFF|INCREG, + SCREG, TANY, + SCREG, TANY, + 0, RDEST, + " fmovd AR,AL ! move double\n", }, + +/* Structure assignment. */ + +{ STASG, INAREG|FOREFF, + SOREG|SNAME, TANY, + SAREG, TPTRTO|TANY, + NSPECIAL, RDEST, + "ZQ", }, + +/* Comparisons. */ + +{ EQ, FORCC, + SAREG, TANY, + SAREG, TANY, + 0, RESCC, + " cmp AL,AR ! eq\n" + " be LC\n" + " nop\n", }, + +{ NE, FORCC, + SAREG, TANY, + SAREG, TANY, + 0, RESCC, + " cmp AL,AR ! ne\n" + " bne LC\n" + " nop\n", }, + +{ OPLOG, FORCC, + SAREG, TANY, + SZERO, TANY, + 0, RESCC, + " O AL,LC\n" + " nop\n", }, + +{ OPLOG, FORCC, + SAREG, TANY, + SAREG, TANY, + NAREG|NASL, RESCC, + " sub AL,AR,A1 ! oplog\n" + " O A1,LC\n" + " nop\n", }, + +{ OPLOG, FORCC, + SAREG, TANY, + SCCON, TANY, + NAREG|NASL, RESCC, + " sub AL,AR,A1 ! oplog sccon\n" + " O A1,LC\n" + " nop\n", }, + +{ OPLOG, FORCC, + SBREG, TFLOAT, + SBREG, TFLOAT, + NBREG, RESCC, + " fcmps AL,AR ! oplog float\n" + " ZF LC\n", }, + +{ OPLOG, FORCC, + SOREG, TFLOAT, + SBREG, TFLOAT, + NBREG, RESCC, + " ld [AL], A1 ! oplog float oreg\n" + " nop\n" + " fcmps A1,AR\n" + " ZF LC\n", }, + +{ OPLOG, FORCC, + SCREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG, RESCC, + " fcmpd AL,AR ! oplog double\n" + " ZF LC\n", }, + +{ OPLOG, FORCC, + SOREG, TDOUBLE, + SCREG, TDOUBLE, + NCREG, RESCC, + " ldd [AL], A1 ! oplog double oreg\n" + " nop\n" + " fcmpd A1,AR\n" + " ZF LC\n", }, + + +/* Load constants to register. */ + +{ OPLTYPE, INAREG, + SCON, TANY, + SNAME, T64, + NAREG, RESC1, + " sethi %h44(AL),A1\t ! load const (u)int64 to reg\n" + " or A1,%m44(AL),A1\n" + " sllx A1,12,A1\n" + " ldx [A1+%l44(AL)],A1\n" + " nop\n", }, +{ OPLTYPE, INAREG, + SCON, TANY, + SNAME, TINT, + NAREG, RESC1, + " sethi %h44(AL),A1\t ! load const int32 to reg\n" + " or A1,%m44(AL),A1\n" + " sllx A1,12,A1\n" + " ldsw [A1+%l44(AL)],A1\n" + " nop\n", }, + +{ OPLTYPE, INAREG, + SCON, TANY, + SNAME, TUNSIGNED, + NAREG, RESC1, + " sethi %h44(AL),A1\t! load const uint32 to reg\n" + " or A1,%m44(AL),A1\n" + " sllx A1,12,A1\n" + " lduw [A1+%l44(AL)],A1\n" + " nop\n", }, +{ OPLTYPE, INAREG, + SCON, TANY, + SNAME, TSHORT, + NAREG, RESC1, + " sethi %h44(AL),A1\t! load const int16 to reg\n" + " or A1,%m44(AL),A1\n" + " sllx A1,12,A1\n" + " ldsh [A1+%l44(AL)],A1\n" + " nop\n", }, +{ OPLTYPE, INAREG, + SCON, TANY, + SNAME, TUSHORT, + NAREG, RESC1, + " sethi %h44(AL),A1\t ! load const uint16 to reg\n" + " or A1,%m44(AL),A1\n" + " sllx A1,12,A1\n" + " lduh [A1+%l44(AL)],A1\n" + " nop\n", }, +{ OPLTYPE, INAREG, + SCON, TANY, + SNAME, TCHAR, + NAREG, RESC1, + " sethi %h44(AL),A1\t\t! load const int8 to reg\n" + " or A1,%m44(AL),A1\n" + " sllx A1,12,A1\n" + " ldsb [A1+%l44(AL)],A1\n" + " nop\n", }, +{ OPLTYPE, INAREG, + SCON, TANY, + SNAME, TUCHAR, + NAREG, RESC1, + " sethi %h44(AL),A1\t! load const uint8 to reg\n" + " or A1,%m44(AL),A1\n" + " sllx A1,12,A1\n" + " ldub [A1+%l44(AL)],A1\n" + " nop\n", }, + +{ OPLTYPE, INBREG, + SBREG, TANY, + SNAME, TANY, + NAREG|NBREG, RESC2, + " sethi %h44(AL),A1\t\t! load const to fp reg\n" + " or A1,%m44(AL),A1\n" + " sllx A1,12,A1\n" + " ld [A1+%l44(AL)],A2\n" + " nop\n", }, + +{ OPLTYPE, INCREG, + SCREG, TANY, + SNAME, TANY, + NAREG|NCREG, RESC2, + " sethi %h44(AL),A1\t\t! load const to fp reg\n" + " or A1,%m44(AL),A1\n" + " sllx A1,12,A1\n" + " ldd [A1+%l44(AL)],A2\n" + " nop\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SCON, TANY, + (2*NAREG), RESC1, + "ZC" }, + +/* Convert LTYPE to reg. */ + +{ OPLTYPE, INAREG, + SAREG, TANY, + SOREG, TCHAR, + NAREG, RESC1, + " ldsb [AL],A1 ! load int8 to reg\n" + " nop\n", }, + +{ OPLTYPE, INAREG, + SAREG, TANY, + SOREG, TUCHAR, + NAREG, RESC1, + " ldub [AL],A1 ! load uint8 to reg\n" + " nop\n", }, + +{ OPLTYPE, INAREG, + SAREG, TANY, + SOREG, TSHORT, + NAREG, RESC1, + " ldsh [AL],A1 ! load int16 to reg\n" + " nop\n", }, + +{ OPLTYPE, INAREG, + SAREG, TANY, + SOREG, TUSHORT, + NAREG, RESC1, + " lduh [AL],A1 ! load uint16 to reg\n" + " nop\n", }, + +{ OPLTYPE, INAREG, + SAREG, TANY, + SOREG, TINT, + NAREG, RESC1, + " ldsw [AL],A1 ! load int32 to reg\n" + " nop\n", }, + +{ OPLTYPE, INAREG, + SAREG, TANY, + SOREG, TUNSIGNED, + NAREG, RESC1, + " lduw [AL],A1 ! load uint32 to reg\n" + " nop\n", }, + +{ OPLTYPE, INAREG, + SAREG, TANY, + SOREG, T64, + NAREG, RESC1, + " ldx [AL],A1 ! load (u)int64 to reg\n" + " nop\n", }, + +{ OPLTYPE, INAREG, + SANY, TANY, + SZERO, TANY, + NAREG, RESC1, + " mov \%g0,A1\t ! load 0 to reg\n", }, + +{ OPLTYPE, INBREG, + SBREG, TFLOAT, + SOREG, TFLOAT, + NBREG, RESC1, + " ld [AL],A1 ! load float to reg\n" + " nop\n", }, + +{ OPLTYPE, INCREG, + SCREG, TDOUBLE, + SOREG, TDOUBLE, + NCREG, RESC1, + " ldd [AL],A1 ! load double to reg\n" + " nop\n", }, + +/* Jumps. */ + +{ GOTO, FOREFF, + SCON, TANY, + SANY, TANY, + 0, RNOP, + " call LL ! goto LL\n" + " nop\n", }, + +{ UCALL, FOREFF, + SCON, TANY, + SANY, TANY, + 0, 0, + " call CL ! void CL()\n" + " nop\n", }, + +{ UCALL, INAREG, + SCON, TANY, + SAREG, TANY, + NAREG, RESC1, + " call CL ! = CL()\n" + " nop\n", }, + +{ CALL, FOREFF, + SCON, TANY, + SANY, TANY, + 0, 0, + " call CL ! void CL(constant)\n" + " nop\n", }, + +{ CALL, INAREG, + SCON, TANY, + SAREG, TANY, + NAREG, RESC1, + " call CL ! = CL(constant)\n" + " nop\n", }, + +{ CALL, INBREG, + SCON, TANY, + SBREG, TFLOAT, + NBREG, RESC1, + " call CL ! = CL(constant)\n" + " nop\n", }, + +{ CALL, INCREG, + SCON, TANY, + SCREG, TDOUBLE, + NCREG, RESC1, + " call CL ! = CL(constant)\n" + " nop\n", }, + +{ CALL, INAREG, + SAREG, TANY, + SAREG, TANY, + NAREG, RESC1, + " call AL ! = AL(args)\n" + " nop\n", }, + +{ CALL, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, 0, + " call AL ! void AL(args)\n" + " nop\n", }, + +{ UCALL, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, 0, + " call AL ! (*AL)()\n" + " nop\n", }, + +{ UCALL, INAREG, + SAREG, TANY, + SAREG, TANY, + NAREG, RESC1, + " call AL ! = (*AL)()\n" + " nop\n", }, + +{ CALL, INAREG, + SAREG, TANY, + SAREG, TANY, + NAREG, RESC1, + " call AL ! = (*AL)(args)\n" + " nop\n", }, + +/* Function arguments. */ + +{ FUNARG, FOREFF, + SAREG, T64, + SANY, TANY, + 0, 0, + " stx AL,[%sp+AR] \t! save func arg to stack\n" + " nop\n", }, + +{ FUNARG, FOREFF, + SAREG, TINT|TUNSIGNED, + SANY, TANY, + 0, 0, + " stw AL,[%sp+AR] \t! save func arg to stack\n" + " nop\n", }, + +{ FUNARG, FOREFF, + SAREG, TSHORT|TUSHORT, + SANY, TANY, + 0, 0, + " sth AL,[%sp+AR] \t! save func arg to stack\n" + " nop\n", }, + +{ FUNARG, FOREFF, + SAREG, TCHAR|TUCHAR, + SANY, TANY, + 0, 0, + " stb AL,[%sp+AR] \t! save func arg to stack\n" + " nop\n", }, + +{ FUNARG, FOREFF, + SBREG, TFLOAT, + SANY, TANY, + 0, 0, + " st AL,[%sp+AR] \t! save func arg to stack\n" + " nop\n", }, + +{ FUNARG, FOREFF, + SCREG, TDOUBLE, + SANY, TANY, + 0, 0, + " std AL,[%sp+AR] \t! save func arg to stack\n" + " nop\n", }, + + +/* Indirection. */ + +{ OPSIMP, INAREG, + SAREG, TANY, + SAREG, TANY, + NAREG|NASR|NASL, RESC1, + " O AL,AR,A1\n", }, + +{ UMUL, INAREG, + SAREG, T64, + SOREG, T64, + NAREG, RESC1, + " ldx [AL],A1 ! (u)int64 load\n" + " nop\n", }, +{ UMUL, INAREG, + SAREG, TINT, + SOREG, TINT, + NAREG, RESC1, + " ldsw [AL],A1 ! int32 load\n" + " nop\n", }, +{ UMUL, INAREG, + SAREG, TUNSIGNED, + SOREG, TUNSIGNED, + NAREG, RESC1, + " lduw [AL],A1 ! uint32 load\n" + " nop\n", }, +{ UMUL, INAREG, + SAREG, TCHAR, + SOREG, TCHAR, + NAREG, RESC1, + " ldsb [AL],A1 ! int8 load\n" + " nop\n", }, +{ UMUL, INAREG, + SAREG, TUCHAR, + SOREG, TUCHAR, + NAREG, RESC1, + " ldub [AL],A1 ! uint8 load\n" + " nop\n", }, +{ UMUL, INAREG, + SAREG, TSHORT, + SOREG, TSHORT, + NAREG, RESC1, + " ldsh [AL],A1 ! int16 load\n" + " nop\n", }, +{ UMUL, INAREG, + SAREG, TUSHORT, + SOREG, TUSHORT, + NAREG, RESC1, + " lduh [AL],A1 ! uint16 load\n" + " nop\n", }, + +{ UMUL, INBREG, + SAREG, TFLOAT, + SOREG, TFLOAT, + NBREG, RESC1, + " ld [AL],A1 ! load float\n" + " nop\n", }, + +{ UMUL, INCREG, + SAREG, TDOUBLE, + SOREG, TDOUBLE, + NCREG, RESC1, + " ldd [AL],A1 ! load double\n" + " nop\n", }, + +{ FREE,FREE,FREE,FREE,FREE,FREE,FREE,FREE, "ERR: printing free op\n" }, + +}; + +int tablesize = sizeof(table)/sizeof(table[0]); diff --git a/compilers/pcc/pcc-1.0.0/arch/vax/CVS/Entries b/compilers/pcc/pcc-1.0.0/arch/vax/CVS/Entries new file mode 100644 index 00000000..97b506f2 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/vax/CVS/Entries @@ -0,0 +1,7 @@ +/code.c/1.8/Sun Feb 8 16:55:08 2009//Tr-1-0-0-RELEASE +/local.c/1.10/Fri Jan 21 21:47:59 2011//Tr-1-0-0-RELEASE +/local2.c/1.11/Sat Nov 22 16:12:25 2008//Tr-1-0-0-RELEASE +/macdefs.h/1.5/Sat Jan 24 21:43:49 2009//Tr-1-0-0-RELEASE +/order.c/1.4/Mon Nov 26 00:10:03 2007//Tr-1-0-0-RELEASE +/table.c/1.3/Mon Oct 29 14:20:22 2007//Tr-1-0-0-RELEASE +D diff --git a/compilers/pcc/pcc-1.0.0/arch/vax/CVS/Repository b/compilers/pcc/pcc-1.0.0/arch/vax/CVS/Repository new file mode 100644 index 00000000..8d661e20 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/vax/CVS/Repository @@ -0,0 +1 @@ +pcc/arch/vax diff --git a/compilers/pcc/pcc-1.0.0/arch/vax/CVS/Root b/compilers/pcc/pcc-1.0.0/arch/vax/CVS/Root new file mode 100644 index 00000000..71e2ccb9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/vax/CVS/Root @@ -0,0 +1 @@ +/cvsroot diff --git a/compilers/pcc/pcc-1.0.0/arch/vax/CVS/Tag b/compilers/pcc/pcc-1.0.0/arch/vax/CVS/Tag new file mode 100644 index 00000000..060fac05 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/vax/CVS/Tag @@ -0,0 +1 @@ +Nr-1-0-0-RELEASE diff --git a/compilers/pcc/pcc-1.0.0/arch/vax/code.c b/compilers/pcc/pcc-1.0.0/arch/vax/code.c new file mode 100644 index 00000000..ee034ec2 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/vax/code.c @@ -0,0 +1,330 @@ +/* $Id: code.c,v 1.8 2009/02/08 16:55:08 ragge Exp $ */ +/* + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code and documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditionsand the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +# include "pass1.h" + +short log2tab[] = {0, 0, 1, 2, 2, 3, 3, 3, 3}; +#define LOG2SZ 9 + +void +defalign(n) { + /* cause the alignment to become a multiple of n */ + n /= SZCHAR; + if( lastloc != PROG && n > 1 ) printf( " .align %d\n", n >= 0 && n < LOG2SZ ? log2tab[n] : 0 ); + } + +/* + * output something to define the current position as label n + */ +void +deflab1(int n) +{ + printf(LABFMT ":\n", n); +} + +void +efcode(){ + /* code for the end of a function */ + if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) + return; + cerror("efcode"); + +#ifdef notyet + if( strftn ){ /* copy output (in R2) to caller */ + register NODE *l, *r; + register struct symtab *p; + register TWORD t; + register int j; + int i; + + p = &stab[curftn]; + t = p->stype; + t = DECREF(t); + + deflab( retlab ); + + i = getlab(); /* label for return area */ + printf(" .data\n" ); + printf(" .align 2\n" ); + deflab1(i); + printf("\t.space %d\n", tsize(t, p->dimoff, p->sizoff)/SZCHAR); + printf(" .text\n" ); + psline(); + printf(" movab " LABFMT ",r1\n", i); + + reached = 1; + l = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff ); + l->rval = 1; /* R1 */ + l->lval = 0; /* no offset */ + r = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff ); + r->rval = 0; /* R0 */ + r->lval = 0; + l = buildtree( UNARY MUL, l, NIL ); + r = buildtree( UNARY MUL, r, NIL ); + l = buildtree( ASSIGN, l, r ); + l->op = FREE; + ecomp( l->left ); + printf( " movab " LABFMT ",r0\n", i ); + /* turn off strftn flag, so return sequence will be generated */ + strftn = 0; + } + branch( retlab ); + printf( " .set .R%d,0x%x\n", ftnno, ent_mask[reg_use] ); + reg_use = 11; + p2bend(); + fdefflag = 0; +#endif + } + +void +bfcode(struct symtab **a, int n) +{ + int i; + + if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) + return; + /* Function returns struct, adjust arg offset */ + for (i = 0; i < n; i++) + a[i]->soffset += SZPOINT(INT); +} + +void +bccode(){ /* called just before the first executable statment */ + /* by now, the automatics and register variables are allocated */ + SETOFF( autooff, SZINT ); +#if 0 + /* set aside store area offset */ + p2bbeg( autooff, regvar ); + reg_use = (reg_use > regvar ? regvar : reg_use); +#endif + } + +void +ejobcode( flag ){ + /* called just before final exit */ + /* flag is 1 if errors, 0 if none */ + } + +void +bjobcode() +{ +} + +#if 0 +aobeg(){ + /* called before removing automatics from stab */ + } + +aocode(p) struct symtab *p; { + /* called when automatic p removed from stab */ + } + +aoend(){ + /* called after removing all automatics from stab */ + } +#endif + +void +defnam( p ) register struct symtab *p; { + /* define the current location as the name p->sname */ + char *n; + + n = p->soname ? p->soname : exname(p->sname); + if( p->sclass == EXTDEF ){ + printf( " .globl %s\n", n ); + } + printf( "%s:\n", n ); + + } + +void +bycode( t, i ){ + /* put byte i+1 in a string */ + + i &= 07; + if( t < 0 ){ /* end of the string */ + if( i != 0 ) printf( "\n" ); + } + + else { /* stash byte t into string */ + if( i == 0 ) printf( " .byte " ); + else printf( "," ); + printf( "0x%x", t ); + if( i == 07 ) printf( "\n" ); + } + } + +int +fldal( t ) unsigned t; { /* return the alignment of field of type t */ + uerror( "illegal field type" ); + return( ALINT ); + } + +void +fldty( p ) struct symtab *p; { /* fix up type of field p */ + ; + } + +/* + * XXX - fix genswitch. + */ +int +mygenswitch(int num, TWORD type, struct swents **p, int n) +{ + return 0; +} + +#ifdef notyet +struct sw heapsw[SWITSZ]; /* heap for switches */ + +genswitch(p,n) register struct sw *p;{ + /* p points to an array of structures, each consisting + of a constant value and a label. + The first is >=0 if there is a default label; + its value is the label number + The entries p[1] to p[n] are the nontrivial cases + */ + register i; + register CONSZ j, range; + register dlab, swlab; + + range = p[n].sval-p[1].sval; + + if( range>0 && range <= 3*n && n>=4 ){ /* implement a direct switch */ + + swlab = getlab(); + dlab = p->slab >= 0 ? p->slab : getlab(); + + /* already in r0 */ + printf(" casel r0,$%ld,$%ld\n", p[1].sval, range); + deflab1(swlab); + for( i=1,j=p[1].sval; i<=n; j++) { + printf(" .word " LABFMT "-" LABFMT "\n", + (j == p[i].sval ? ((j=p[i++].sval), p[i-1].slab) : dlab), + swlab); + } + + if( p->slab >= 0 ) branch( dlab ); + else deflab1(dlab); + return; + + } + + if( n>8 ) { /* heap switch */ + + heapsw[0].slab = dlab = p->slab >= 0 ? p->slab : getlab(); + makeheap(p, n, 1); /* build heap */ + + walkheap(1, n); /* produce code */ + + if( p->slab >= 0 ) + branch( dlab ); + else + deflab1(dlab); + return; + } + + /* debugging code */ + + /* out for the moment + if( n >= 4 ) werror( "inefficient switch: %d, %d", n, (int) (range/n) ); + */ + + /* simple switch code */ + + for( i=1; i<=n; ++i ){ + /* already in r0 */ + + printf( " cmpl r0,$" ); + printf( CONFMT, p[i].sval ); + printf( "\n jeql " LBLFMT "\n", p[i].slab ); + } + + if( p->slab>=0 ) branch( p->slab ); + } + +makeheap(p, m, n) +register struct sw *p; +{ + register int q; + + q = select(m); + heapsw[n] = p[q]; + if( q>1 ) makeheap(p, q-1, 2*n); + if( q m ) break; + l = ((k = i/2 - 1) + 1)/2; + return( l + (m-k < l ? m-k : l)); +} + +walkheap(start, limit) +{ + int label; + + + if( start > limit ) return; + printf(" cmpl r0,$%d\n", heapsw[start].sval); + printf(" jeql " LBLFMT "\n", heapsw[start].slab); + if( (2*start) > limit ) { + printf(" jbr " LBLFMT "\n", heapsw[0].slab); + return; + } + if( (2*start+1) <= limit ) { + label = getlab(); + printf(" jgtr " LBLFMT "\n", label); + } else + printf(" jgtr " LBLFMT "\n", heapsw[0].slab); + walkheap( 2*start, limit); + if( (2*start+1) <= limit ) { + deflab1(label); + walkheap( 2*start+1, limit); + } +} +#endif +/* + * Called with a function call with arguments as argument. + * This is done early in buildtree() and only done once. + */ +NODE * +funcode(NODE *p) +{ + return p; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/vax/local.c b/compilers/pcc/pcc-1.0.0/arch/vax/local.c new file mode 100644 index 00000000..eff6bd7d --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/vax/local.c @@ -0,0 +1,511 @@ +/* $Id: local.c,v 1.10 2011/01/21 21:47:59 ragge Exp $ */ +/* + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code and documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditionsand the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +# include "pass1.h" + +/* this file contains code which is dependent on the target machine */ + +#if 0 +NODE * +cast( p, t ) register NODE *p; TWORD t; { + /* cast node p to type t */ + + p = buildtree( CAST, block( NAME, NIL, NIL, t, 0, (int)t ), p ); + p->left->op = FREE; + p->op = FREE; + return( p->right ); + } +#endif + +NODE * +clocal(p) NODE *p; { + + /* this is called to do local transformations on + an expression tree preparitory to its being + written out in intermediate code. + */ + + /* the major essential job is rewriting the + automatic variables and arguments in terms of + REG and OREG nodes */ + /* conversion ops which are not necessary are also clobbered here */ + /* in addition, any special features (such as rewriting + exclusive or) are easily handled here as well */ + + register struct symtab *q; + register NODE *r; + register int o; + register int m, ml; + + switch( o = p->n_op ){ + + case NAME: + if((q = p->n_sp) == 0 ) { /* already processed; ignore... */ + return(p); + } + switch( q->sclass ){ + + case AUTO: + case PARAM: + /* fake up a structure reference */ + r = block( REG, NIL, NIL, PTR+STRTY, 0, 0 ); + r->n_lval = 0; + r->n_rval = (q->sclass==AUTO?STKREG:ARGREG); + p = stref( block( STREF, r, p, 0, 0, 0 ) ); + break; + + case STATIC: + if( q->slevel == 0 ) break; + p->n_lval = 0; + p->n_rval = -q->soffset; + break; + + case REGISTER: + p->n_op = REG; + p->n_lval = 0; + p->n_rval = q->soffset; + break; + + } + break; + + case PCONV: + /* do pointer conversions for char and longs */ + ml = p->n_left->n_type; + if( ( ml==CHAR || ml==UCHAR || ml==SHORT || ml==USHORT ) && p->n_left->n_op != ICON ) break; + + /* pointers all have the same representation; the type is inherited */ + + inherit: + p->n_left->n_type = p->n_type; + p->n_left->n_df = p->n_df; + p->n_left->n_sue = p->n_sue; + r = p->n_left; + nfree(p); + return( r ); + + case SCONV: + m = (p->n_type == FLOAT || p->n_type == DOUBLE ); + ml = (p->n_left->n_type == FLOAT || p->n_left->n_type == DOUBLE ); + if( m != ml ) break; + + /* now, look for conversions downwards */ + + m = p->n_type; + ml = p->n_left->n_type; + if( p->n_left->n_op == ICON ){ /* simulate the conversion here */ + CONSZ val; + val = p->n_left->n_lval; + switch( m ){ + case CHAR: + p->n_left->n_lval = (char) val; + break; + case UCHAR: + p->n_left->n_lval = val & 0XFF; + break; + case USHORT: + p->n_left->n_lval = val & 0XFFFFL; + break; + case SHORT: + p->n_left->n_lval = (short)val; + break; + case UNSIGNED: + p->n_left->n_lval = val & 0xFFFFFFFFL; + break; + case INT: + p->n_left->n_lval = (int)val; + break; + } + p->n_left->n_type = m; + } + else { + /* meaningful ones are conversion of int to char, int to short, + and short to char, and unsigned version of them */ + if( m==CHAR || m==UCHAR ){ + if( ml!=CHAR && ml!= UCHAR ) break; + } + else if( m==SHORT || m==USHORT ){ + if( ml!=CHAR && ml!=UCHAR && ml!=SHORT && ml!=USHORT ) break; + } + } + + /* clobber conversion */ + if( tlen(p) == tlen(p->n_left) ) goto inherit; + r = p->n_left; + nfree(p); + return( r ); /* conversion gets clobbered */ + + case PVCONV: + case PMCONV: + if( p->n_right->n_op != ICON ) cerror( "bad conversion", 0); + r = buildtree( o==PMCONV?MUL:DIV, p->n_left, p->n_right); + nfree(p); + return r; + + case RS: + case RSEQ: + /* convert >> to << with negative shift count */ + /* only if type of left operand is not unsigned */ + if( ISUNSIGNED(p->n_left->n_type) ) break; + p->n_right = buildtree( UMINUS, p->n_right, NIL ); + if( p->n_op == RS ) p->n_op = LS; + else p->n_op = LSEQ; + break; + + case FORCE: + p->n_op = ASSIGN; + p->n_right = p->n_left; + p->n_left = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT)); + p->n_left->n_rval = p->n_left->n_type == BOOL ? + RETREG(CHAR) : RETREG(p->n_type); + break; + + case STCALL: + case CALL: + /* Fix function call arguments. On vax, just add funarg */ + for (r = p->n_right; r->n_op == CM; r = r->n_left) { + if (r->n_right->n_op != STARG && + r->n_right->n_op != FUNARG) + r->n_right = block(FUNARG, r->n_right, NIL, + r->n_right->n_type, r->n_right->n_df, + r->n_right->n_sue); + } + if (r->n_op != STARG && r->n_op != FUNARG) { + NODE *l = talloc(); + *l = *r; + r->n_op = FUNARG; r->n_left = l; r->n_type = l->n_type; + } + break; + } + + return(p); +} + +void +myp2tree(NODE *p) +{ + struct symtab *sp; + int o = p->n_op, i; + + if (o != FCON) + return; + + sp = inlalloc(sizeof(struct symtab)); + sp->sclass = STATIC; + sp->ssue = MKSUE(p->n_type); + sp->slevel = 1; /* fake numeric label */ + sp->soffset = getlab(); + sp->sflags = 0; + sp->stype = p->n_type; + sp->squal = (CON >> TSHIFT); + + defloc(sp); + ninval(0, sp->ssue->suesize, p); + + p->n_op = NAME; + p->n_lval = 0; + p->n_sp = sp; + +} + +/* + * Can we take & of a NAME? + */ +int +andable(NODE *p) +{ + + if ((p->n_type & ~BTMASK) == FTN) + return 1; /* functions are called by name */ + return 0; /* Delay name reference to table, for PIC code generation */ +} + +void +cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */ + autooff = AUTOINIT; + } + +int +cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */ + return(1); /* all are now */ + } + +NODE * +offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue) +{ + + /* return a node, for structure references, which is suitable for + being added to a pointer of type t, in order to be off bits offset + into a structure */ + + register NODE *p; + + /* t, d, and s are the type, dimension offset, and sizeoffset */ + /* in general they are necessary for offcon, but not on H'well */ + + p = bcon(0); + p->n_lval = off/SZCHAR; + return(p); + + } + +void +spalloc(NODE *t, NODE *p, OFFSZ off) +{ + cerror("spalloc"); +} + +static int inbits, inval; + +/* + * set fsz bits in sequence to zero. + */ +void +zbits(OFFSZ off, int fsz) +{ + int m; + + if (idebug) + printf("zbits off %lld, fsz %d inbits %d\n", off, fsz, inbits); + if ((m = (inbits % SZCHAR))) { + m = SZCHAR - m; + if (fsz < m) { + inbits += fsz; + return; + } else { + fsz -= m; + printf("\t.byte %d\n", inval); + inval = inbits = 0; + } + } + if (fsz >= SZCHAR) { + printf("\t.space %d\n", fsz/SZCHAR); + fsz -= (fsz/SZCHAR) * SZCHAR; + } + if (fsz) { + inval = 0; + inbits = fsz; + } +} + +/* + * Initialize a bitfield. + */ +void +infld(CONSZ off, int fsz, CONSZ val) +{ + if (idebug) + printf("infld off %lld, fsz %d, val %lld inbits %d\n", + off, fsz, val, inbits); + val &= ((CONSZ)1 << fsz)-1; + while (fsz + inbits >= SZCHAR) { + inval |= (val << inbits); + printf("\t.byte %d\n", inval & 255); + fsz -= (SZCHAR - inbits); + val >>= (SZCHAR - inbits); + inval = inbits = 0; + } + if (fsz) { + inval |= (val << inbits); + inbits += fsz; + } +} + + +char * +exname( p ) char *p; { + /* make a name look like an external name in the local machine */ + /* vad is elf now */ + if (p == NULL) + return ""; + return( p ); + } + +TWORD +ctype(TWORD type ){ /* map types which are not defined on the local machine */ + switch( BTYPE(type) ){ + + case LONG: + MODTYPE(type,INT); + break; + + case ULONG: + MODTYPE(type,UNSIGNED); + break; + + case LDOUBLE: /* for now */ + MODTYPE(type,DOUBLE); + } + return( type ); + } + +void +calldec(NODE *p, NODE *q) +{ +} + +void +extdec(struct symtab *q) +{ +} + +void +commdec( struct symtab *q ){ /* make a common declaration for id, if reasonable */ + OFFSZ off; + + printf( " .comm %s,", q->soname ? q->soname : exname( q->sname ) ); + off = tsize( q->stype, q->sdf, q->ssue ); + printf( CONFMT, off/SZCHAR ); + printf( "\n" ); + } + +/* make a local common declaration for id, if reasonable */ +void +lcommdec(struct symtab *q) +{ + int off; + + off = tsize(q->stype, q->sdf, q->ssue); + off = (off+(SZCHAR-1))/SZCHAR; + if (q->slevel == 0) + printf(" .lcomm %s,0%o\n", q->soname ? q->soname : exname(q->sname), off); + else + printf(" .lcomm " LABFMT ",0%o\n", q->soffset, off); +} + + +static char *loctbl[] = { "text", "data", "section .rodata", "section .rodata" }; + +void +setloc1(int locc) +{ + if (locc == lastloc) + return; + lastloc = locc; + printf(" .%s\n", loctbl[locc]); +} + +/* + * print out a constant node, may be associated with a label. + * Do not free the node after use. + * off is bit offset from the beginning of the aggregate + * fsz is the number of bits this is referring to + * XXX - floating point constants may be wrong if cross-compiling. + */ +void +ninval(CONSZ off, int fsz, NODE *p) +{ + union { float f; double d; long double l; int i[3]; } u; + struct symtab *q; + TWORD t; + + t = p->n_type; + if (t > BTMASK) + t = INT; /* pointer */ + + if (p->n_op != ICON && p->n_op != FCON) + cerror("ninval: init node not constant"); + + if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT) + uerror("element not constant"); + + switch (t) { + case LONGLONG: + case ULONGLONG: + printf("\t.long 0x%x", (int)p->n_lval); + printf("\t.long 0x%x", (int)(p->n_lval >> 32)); + break; + case INT: + case UNSIGNED: + printf("\t.long 0x%x", (int)p->n_lval); + if ((q = p->n_sp) != NULL) { + if ((q->sclass == STATIC && q->slevel > 0)) { + printf("+" LABFMT, q->soffset); + } else + printf("+%s", q->soname ? q->soname : exname(q->sname)); + } + printf("\n"); + break; + case SHORT: + case USHORT: + printf("\t.short 0x%x\n", (int)p->n_lval & 0xffff); + break; + case BOOL: + if (p->n_lval > 1) + p->n_lval = p->n_lval != 0; + /* FALLTHROUGH */ + case CHAR: + case UCHAR: + printf("\t.byte %d\n", (int)p->n_lval & 0xff); + break; + case LDOUBLE: + u.i[2] = 0; + u.l = (long double)p->n_dcon; + printf("\t.long\t0x%x,0x%x,0x%x\n", u.i[0], u.i[1], u.i[2]); + break; + case DOUBLE: + u.d = (double)p->n_dcon; + printf("\t.long\t0x%x,0x%x\n", u.i[0], u.i[1]); + break; + case FLOAT: + u.f = (float)p->n_dcon; + printf("\t.long\t0x%x\n", u.i[0]); + break; + default: + cerror("ninval"); + } + +} +/* + * Give target the opportunity of handling pragmas. + */ +int +mypragma(char *str) +{ + return 0; +} + +/* + * Called when a identifier has been declared, to give target last word. + */ +void +fixdef(struct symtab *sp) +{ +} + +void +pass1_lastchance(struct interpass *ip) +{ +} diff --git a/compilers/pcc/pcc-1.0.0/arch/vax/local2.c b/compilers/pcc/pcc-1.0.0/arch/vax/local2.c new file mode 100644 index 00000000..1a9b7595 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/vax/local2.c @@ -0,0 +1,1036 @@ +/* $Id: local2.c,v 1.11 2008/11/22 16:12:25 ragge Exp $ */ +/* + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code and documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditionsand the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +# include "pass2.h" +# include "ctype.h" +/* a lot of the machine dependent parts of the second pass */ + +static void prtype(NODE *n); +static void acon(NODE *p); + +/* + * Print out the prolog assembler. + * addto and regoff are already calculated. + */ +void +prologue(struct interpass_prolog *ipp) +{ + if (ipp->ipp_vis) + printf(" .globl %s\n", ipp->ipp_name); + printf(" .align 4\n"); + printf("%s:\n", ipp->ipp_name); + printf(" .word 0x%x\n", ipp->ipp_regs[0]); + if (p2maxautooff) + printf(" subl2 $%d,%%sp\n", p2maxautooff); +} + +/* + * Called after all instructions in a function are emitted. + * Generates code for epilog here. + */ +void +eoftn(struct interpass_prolog *ipp) +{ + if (ipp->ipp_ip.ip_lbl == 0) + return; /* no code needs to be generated */ + printf(" ret\n"); +} + +struct hoptab { int opmask; char * opstring; } ioptab[] = { + + { PLUS, "add", }, + { MINUS, "sub", }, + { MUL, "mul", }, + { DIV, "div", }, + { OR, "bis", }, + { ER, "xor", }, + { AND, "bic", }, + { -1, "" }, +}; + +void +hopcode( f, o ){ + /* output the appropriate string from the above table */ + + register struct hoptab *q; + + for( q = ioptab; q->opmask>=0; ++q ){ + if( q->opmask == o ){ + printf( "%s", q->opstring ); +/* tbl + if( f == 'F' ) printf( "e" ); + else if( f == 'D' ) printf( "d" ); + tbl */ +/* tbl */ + switch( f ) { + case 'L': + case 'W': + case 'B': + case 'D': + case 'F': + printf("%c", tolower(f)); + break; + + } +/* tbl */ + return; + } + } + cerror( "no hoptab for %s", opst[o] ); + } + +char * +rnames[] = { /* keyed to register number tokens */ + + "r0", "r1", "r2", "r3", "r4", "r5", + "r6", "r7", "r8", "r9", "r10", "r11", + "ap", "fp", "sp", "pc", + /* The concatenated regs has the name of the lowest */ + "r0", "r1", "r2", "r3", "r4", "r5", + "r6", "r7", "r8", "r9", "r10" + }; + +int +tlen(p) NODE *p; +{ + switch(p->n_type) { + case CHAR: + case UCHAR: + return(1); + + case SHORT: + case USHORT: + return(2); + + case DOUBLE: + case LDOUBLE: + case LONGLONG: + case ULONGLONG: + return(8); + + default: + return(4); + } +} + +static int +mixtypes(NODE *p, NODE *q) +{ + TWORD tp, tq; + + tp = p->n_type; + tq = q->n_type; + + return( (tp==FLOAT || tp==DOUBLE) != + (tq==FLOAT || tq==DOUBLE) ); +} + +void +prtype(NODE *n) +{ + switch (n->n_type) + { + case DOUBLE: + printf("d"); + return; + + case FLOAT: + printf("f"); + return; + + case LONG: + case ULONG: + case INT: + case UNSIGNED: + printf("l"); + return; + + case SHORT: + case USHORT: + printf("w"); + return; + + case CHAR: + case UCHAR: + printf("b"); + return; + + default: + if ( !ISPTR( n->n_type ) ) cerror("zzzcode- bad type"); + else { + printf("l"); + return; + } + } +} + +void +zzzcode( p, c ) register NODE *p; { + int m; + int val; + switch( c ){ + + case 'N': /* logical ops, turned into 0-1 */ + /* use register given by register 1 */ + cbgen( 0, m=getlab2()); + deflab( p->n_label ); + printf( " clrl %s\n", rnames[getlr( p, '1' )->n_rval] ); + deflab( m ); + return; + + case 'A': + { + register NODE *l, *r; + + if (xdebug) e2print(p, 0, &val, &val); + r = getlr(p, 'R'); + if (optype(p->n_op) == LTYPE || p->n_op == UMUL) { + l = resc; + l->n_type = (r->n_type==FLOAT || r->n_type==DOUBLE ? DOUBLE : INT); + } else + l = getlr(p, 'L'); + if (r->n_op == ICON && r->n_name[0] == '\0') { + if (r->n_lval == 0) { + printf("clr"); + prtype(l); + printf(" "); + adrput(stdout, l); + return; + } + if (r->n_lval < 0 && r->n_lval >= -63) { + printf("mneg"); + prtype(l); + r->n_lval = -r->n_lval; + goto ops; + } + r->n_type = (r->n_lval < 0 ? + (r->n_lval >= -128 ? CHAR + : (r->n_lval >= -32768 ? SHORT + : INT )) : r->n_type); + r->n_type = (r->n_lval >= 0 ? + (r->n_lval <= 63 ? INT + : ( r->n_lval <= 127 ? CHAR + : (r->n_lval <= 255 ? UCHAR + : (r->n_lval <= 32767 ? SHORT + : (r->n_lval <= 65535 ? USHORT + : INT ))))) : r->n_type ); + } + if (l->n_op == REG && l->n_type != FLOAT && l->n_type != DOUBLE) + l->n_type = INT; + if (!mixtypes(l,r)) + { + if (tlen(l) == tlen(r)) + { + printf("mov"); + prtype(l); + goto ops; + } + else if (tlen(l) > tlen(r) && ISUNSIGNED(r->n_type)) + { + printf("movz"); + } + else + { + printf("cvt"); + } + } + else + { + printf("cvt"); + } + prtype(r); + prtype(l); + ops: + printf(" "); + adrput(stdout, r); + printf(","); + adrput(stdout, l); + return; + } + + case 'C': /* num words pushed on arg stack */ + if (p->n_op == STCALL || p->n_op == USTCALL) + p->n_qual++; + printf("$%d", p->n_qual); + break; + + case 'D': /* INCR and DECR */ + zzzcode(p->n_left, 'A'); + printf("\n "); + +#if 0 + case 'E': /* INCR and DECR, FOREFF */ + if (p->n_right->n_lval == 1) + { + printf("%s", (p->n_op == INCR ? "inc" : "dec") ); + prtype(p->n_left); + printf(" "); + adrput(stdout, p->n_left); + return; + } + printf("%s", (p->n_op == INCR ? "add" : "sub") ); + prtype(p->n_left); + printf("2 "); + adrput(stdout, p->n_right); + printf(","); + adrput(p->n_left); + return; +#endif + + case 'F': /* register type of right operand */ + { + register NODE *n; + extern int xdebug; + register int ty; + + n = getlr( p, 'R' ); + ty = n->n_type; + + if (xdebug) printf("->%d<-", ty); + + if ( ty==DOUBLE) printf("d"); + else if ( ty==FLOAT ) printf("f"); + else printf("l"); + return; + } + + case 'J': /* jump or ret? */ + { + extern struct interpass_prolog *epp; + struct interpass *ip = + DLIST_PREV((struct interpass *)epp, qelem); + if (ip->type != IP_DEFLAB || + ip->ip_lbl != getlr(p, 'L')->n_lval) + expand(p, FOREFF, "jbr LL"); + else + printf("ret"); + } + break; + + case 'L': /* type of left operand */ + case 'R': /* type of right operand */ + { + register NODE *n; + extern int xdebug; + + n = getlr ( p, c); + if (xdebug) printf("->%d<-", n->n_type); + + prtype(n); + return; + } + + case 'Z': /* complement mask for bit instr */ + printf("$%Ld", ~p->n_right->n_lval); + return; + + case 'U': /* 32 - n, for unsigned right shifts */ + printf("$" CONFMT, 32 - p->n_right->n_lval ); + return; + + case 'T': /* rounded structure length for arguments */ + { + int size; + + size = p->n_stsize; + SETOFF( size, 4); + printf("$%d", size); + return; + } + + case 'S': /* structure assignment */ + { + register NODE *l, *r; + register int size; + + l = r = NULL; /* XXX gcc */ + if( p->n_op == STASG ){ + l = p->n_left; + r = p->n_right; + + } + else if( p->n_op == STARG ){ /* store an arg into a temporary */ + l = getlr( p, '3' ); + r = p->n_left; + } + else cerror( "STASG bad" ); + + if( r->n_op == ICON ) r->n_op = NAME; + else if( r->n_op == REG ) r->n_op = OREG; + else if( r->n_op != OREG ) cerror( "STASG-r" ); + + size = p->n_stsize; + + if( size <= 0 || size > 65535 ) + cerror("structure size <0=0 or >65535"); + + switch(size) { + case 1: + printf(" movb "); + break; + case 2: + printf(" movw "); + break; + case 4: + printf(" movl "); + break; + case 8: + printf(" movq "); + break; + default: + printf(" movc3 $%d,", size); + break; + } + adrput(stdout, r); + printf(","); + adrput(stdout, l); + printf("\n"); + + if( r->n_op == NAME ) r->n_op = ICON; + else if( r->n_op == OREG ) r->n_op = REG; + + } + break; + + default: + comperr("illegal zzzcode '%c'", c); + } + } + +void +rmove( int rt,int rs, TWORD t ){ + printf( " %s %s,%s\n", + (t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")), + rnames[rs], rnames[rt] ); + } + +#if 0 +setregs(){ /* set up temporary registers */ + fregs = 6; /* tbl- 6 free regs on VAX (0-5) */ + ; + } + +szty(t){ /* size, in registers, needed to hold thing of type t */ + return( (t==DOUBLE||t==FLOAT) ? 2 : 1 ); + } +#endif + +int +rewfld( p ) NODE *p; { + return(1); + } + +#if 0 +callreg(p) NODE *p; { + return( R0 ); + } + +base( p ) register NODE *p; { + register int o = p->op; + + if( (o==ICON && p->name[0] != '\0')) return( 100 ); /* ie no base reg */ + if( o==REG ) return( p->rval ); + if( (o==PLUS || o==MINUS) && p->left->op == REG && p->right->op==ICON) + return( p->left->rval ); + if( o==OREG && !R2TEST(p->rval) && (p->type==INT || p->type==UNSIGNED || ISPTR(p->type)) ) + return( p->rval + 0200*1 ); + if( o==INCR && p->left->op==REG ) return( p->left->rval + 0200*2 ); + if( o==ASG MINUS && p->left->op==REG) return( p->left->rval + 0200*4 ); + if( o==UNARY MUL && p->left->op==INCR && p->left->left->op==REG + && (p->type==INT || p->type==UNSIGNED || ISPTR(p->type)) ) + return( p->left->left->rval + 0200*(1+2) ); + return( -1 ); + } + +offset( p, tyl ) register NODE *p; int tyl; { + + if( tyl==1 && p->op==REG && (p->type==INT || p->type==UNSIGNED) ) return( p->rval ); + if( (p->op==LS && p->left->op==REG && (p->left->type==INT || p->left->type==UNSIGNED) && + (p->right->op==ICON && p->right->name[0]=='\0') + && (1<right->lval)==tyl)) + return( p->left->rval ); + return( -1 ); + } +#endif + +#if 0 +void +makeor2( p, q, b, o) register NODE *p, *q; register int b, o; { + register NODE *t; + NODE *f; + + p->n_op = OREG; + f = p->n_left; /* have to free this subtree later */ + + /* init base */ + switch (q->n_op) { + case ICON: + case REG: + case OREG: + t = q; + break; + + case MINUS: + q->n_right->n_lval = -q->n_right->n_lval; + case PLUS: + t = q->n_right; + break; + + case UMUL: + t = q->n_left->n_left; + break; + + default: + cerror("illegal makeor2"); + t = NULL; /* XXX gcc */ + } + + p->n_lval = t->n_lval; + p->n_name = t->n_name; + + /* init offset */ + p->n_rval = R2PACK( (b & 0177), o, (b>>7) ); + + tfree(f); + return; + } + +int +canaddr( p ) NODE *p; { + register int o = p->n_op; + + if( o==NAME || o==REG || o==ICON || o==OREG || (o==UMUL && shumul(p->n_left, STARNM|SOREG)) ) return(1); + return(0); + } + +shltype( o, p ) register NODE *p; { + return( o== REG || o == NAME || o == ICON || o == OREG || ( o==UMUL && shumul(p->n_left, STARNM|SOREG)) ); + } +#endif + +int +fldexpand(NODE *p, int cookie, char **cp) +{ + return 0; +} + +int +flshape( p ) register NODE *p; { + return( p->n_op == REG || p->n_op == NAME || p->n_op == ICON || + (p->n_op == OREG && (!R2TEST(p->n_rval) || tlen(p) == 1)) ); + } + +int +shtemp( p ) register NODE *p; { + if( p->n_op == STARG ) p = p->n_left; + return( p->n_op==NAME || p->n_op ==ICON || p->n_op == OREG || (p->n_op==UMUL && shumul(p->n_left, STARNM|SOREG)) ); + } + +int +shumul( p, shape ) register NODE *p; int shape; { + register int o; + extern int xdebug; + + if (xdebug) { + printf("\nshumul:op=%d,lop=%d,rop=%d", p->n_op, p->n_left->n_op, p->n_right->n_op); + printf(" prname=%s,plty=%d, prlval=%lld\n", p->n_right->n_name, p->n_left->n_type, p->n_right->n_lval); + } + + + o = p->n_op; + if( o == NAME || (o == OREG && !R2TEST(p->n_rval)) || o == ICON ) + if (shape & STARNM) + return SRDIR; + +#ifdef notyet + if( ( o == INCR || o == ASG MINUS ) && + ( p->n_left->n_op == REG && p->n_right->n_op == ICON ) && + p->n_right->n_name[0] == '\0' ) + { + switch (p->n_left->n_type) + { + case CHAR|PTR: + case UCHAR|PTR: + o = 1; + break; + + case SHORT|PTR: + case USHORT|PTR: + o = 2; + break; + + case INT|PTR: + case UNSIGNED|PTR: + case LONG|PTR: + case ULONG|PTR: + case FLOAT|PTR: + o = 4; + break; + + case DOUBLE|PTR: + o = 8; + break; + + default: + if ( ISPTR(p->n_left->n_type) ) { + o = 4; + break; + } + else return(0); + } + return( p->n_right->n_lval == o ? STARREG : 0); + } +#endif + + return( SRNOPE ); + } + +void +adrcon( val ) CONSZ val; { + printf( "$" ); + printf( CONFMT, val ); + } + +void +conput(FILE *fp, NODE *p) +{ + switch( p->n_op ){ + + case ICON: + acon( p ); + return; + + case REG: + printf( "%s", rnames[p->n_rval] ); + return; + + default: + cerror( "illegal conput" ); + } + } + +void +insput( p ) register NODE *p; { + cerror( "insput" ); + } + +void +upput( p , size) register NODE *p; { + cerror( "upput" ); + } + +void +adrput(FILE *fp, NODE *p) +{ + register int r; + /* output an address, with offsets, from p */ + + if( p->n_op == FLD ){ + p = p->n_left; + } + switch( p->n_op ){ + + case NAME: + acon( p ); + return; + + case ICON: + /* addressable value of the constant */ + if (p->n_name[0] == '\0') /* uses xxxab */ + printf("$"); + acon(p); + return; + + case REG: + printf( "%s", rnames[p->n_rval] ); + return; + + case OREG: + r = p->n_rval; + if( R2TEST(r) ){ /* double indexing */ + register int flags; + + flags = R2UPK3(r); + if( flags & 1 ) printf("*"); + if( flags & 4 ) printf("-"); + if( p->n_lval != 0 || p->n_name[0] != '\0' ) acon(p); + if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] ); + if( flags & 2 ) printf("+"); + printf( "[%s]", rnames[R2UPK2(r)] ); + return; + } + if( r == AP ){ /* in the argument region */ + if( p->n_lval <= 0 || p->n_name[0] != '\0' ) werror( "bad arg temp" ); + printf( CONFMT, p->n_lval ); + printf( "(ap)" ); + return; + } + if( p->n_lval != 0 || p->n_name[0] != '\0') acon( p ); + printf( "(%s)", rnames[p->n_rval] ); + return; + + case UMUL: + /* STARNM or STARREG found */ + if( tshape(p, STARNM) ) { + printf( "*" ); + adrput(0, p->n_left); + } + else { /* STARREG - really auto inc or dec */ + register NODE *q; + +/* tbl + p = p->n_left; + p->n_left->n_op = OREG; + if( p->n_op == INCR ) { + adrput( p->n_left ); + printf( "+" ); + } + else { + printf( "-" ); + adrput( p->n_left ); + } + tbl */ +#ifdef notyet + printf("%c(%s)%c", (p->n_left->n_op==INCR ? '\0' : '-'), + rnames[p->n_left->n_left->n_rval], + (p->n_left->n_op==INCR ? '+' : '\0') ); +#else + printf("%c(%s)%c", '-', + rnames[p->n_left->n_left->n_rval], + '\0' ); +#endif + p->n_op = OREG; + p->n_rval = p->n_left->n_left->n_rval; + q = p->n_left; +#ifdef notyet + + p->n_lval = (p->n_left->n_op == INCR ? -p->n_left->n_right->n_lval : 0); +#else + p->n_lval = 0; +#endif + p->n_name[0] = '\0'; + tfree(q); + } + return; + + default: + cerror( "illegal address" ); + return; + } + +} + +/* + * print out a constant + */ +void +acon(NODE *p) +{ + + if (p->n_name[0] == '\0') { + printf(CONFMT, p->n_lval); + } else if( p->n_lval == 0 ) { + printf("%s", p->n_name); + } else { + printf("%s+", p->n_name); + printf(CONFMT, p->n_lval); + } +} + +#if 0 +genscall( p, cookie ) register NODE *p; { + /* structure valued call */ + return( gencall( p, cookie ) ); + } + +/* tbl */ +int gc_numbytes; +/* tbl */ + +gencall( p, cookie ) register NODE *p; { + /* generate the call given by p */ + register NODE *p1, *ptemp; + register temp, temp1; + register m; + + if( p->right ) temp = argsize( p->right ); + else temp = 0; + + if( p->op == STCALL || p->op == UNARY STCALL ){ + /* set aside room for structure return */ + + if( p->stsize > temp ) temp1 = p->stsize; + else temp1 = temp; + } + + if( temp > maxargs ) maxargs = temp; + SETOFF(temp1,4); + + if( p->right ){ /* make temp node, put offset in, and generate args */ + ptemp = talloc(); + ptemp->op = OREG; + ptemp->lval = -1; + ptemp->rval = SP; + ptemp->name[0] = '\0'; + ptemp->rall = NOPREF; + ptemp->su = 0; + genargs( p->right, ptemp ); + nfree(ptemp); + } + + p1 = p->left; + if( p1->op != ICON ){ + if( p1->op != REG ){ + if( p1->op != OREG || R2TEST(p1->rval) ){ + if( p1->op != NAME ){ + order( p1, INAREG ); + } + } + } + } + +/* + if( p1->op == REG && p->rval == R5 ){ + cerror( "call register overwrite" ); + } + */ +/* tbl + setup gc_numbytes so reference to ZC works */ + + gc_numbytes = temp; +/* tbl */ + + p->op = UNARY CALL; + m = match( p, INTAREG|INTBREG ); +/* tbl + switch( temp ) { + case 0: + break; + case 2: + printf( " tst (sp)+\n" ); + break; + case 4: + printf( " cmp (sp)+,(sp)+\n" ); + break; + default: + printf( " add $%d,sp\n", temp); + } + tbl */ + return(m != MDONE); + } +#endif + +static char * +ccbranches[] = { + "jeql", + "jneq", + "jleq", + "jlss", + "jgeq", + "jgtr", + "jlequ", + "jlssu", + "jgequ", + "jgtru", +}; + +/* + * printf conditional and unconditional branches + */ +void +cbgen(int o, int lab) +{ + + if (o == 0) { + printf(" jbr " LABFMT "\n", lab); + } else { + if (o > UGT) + comperr("bad conditional branch: %s", opst[o]); + printf("\t%s\t" LABFMT "\n", ccbranches[o-EQ], lab); + } +} + +static void +optim2(NODE *p, void *arg) +{ + /* do local tree transformations and optimizations */ + + register NODE *r; + + switch( p->n_op ) { + + case AND: + /* commute L and R to eliminate compliments and constants */ + if( (p->n_left->n_op==ICON&&p->n_left->n_name[0]==0) || p->n_left->n_op==COMPL ) { + r = p->n_left; + p->n_left = p->n_right; + p->n_right = r; + } +#if 0 + case ASG AND: + /* change meaning of AND to ~R&L - bic on pdp11 */ + r = p->n_right; + if( r->op==ICON && r->name[0]==0 ) { /* compliment constant */ + r->lval = ~r->lval; + } + else if( r->op==COMPL ) { /* ~~A => A */ + r->op = FREE; + p->right = r->left; + } + else { /* insert complement node */ + p->right = talloc(); + p->right->op = COMPL; + p->right->rall = NOPREF; + p->right->type = r->type; + p->right->left = r; + p->right->right = NULL; + } + break; +#endif + } + } + +void +myreader(struct interpass *ipole) +{ + struct interpass *ip; + + DLIST_FOREACH(ip, ipole, qelem) { + if (ip->type != IP_NODE) + continue; + walkf(ip->ip_node, optim2, 0); + } +} + +void +mycanon(NODE *p) +{ +} + +void +myoptim(struct interpass *ip) +{ +} + +/* + * Return argument size in regs. + */ +static int +argsiz(NODE *p) +{ + TWORD t = p->n_type; + + if (t == STRTY || t == UNIONTY) + return p->n_stsize/(SZINT/SZCHAR); + return szty(t); +} + +/* + * Last chance to do something before calling a function. + */ +void +lastcall(NODE *p) +{ + NODE *op = p; + int size = 0; + + /* Calculate argument sizes */ + p->n_qual = 0; + if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL) + return; + for (p = p->n_right; p->n_op == CM; p = p->n_left) + size += argsiz(p->n_right); + size += argsiz(p); + op->n_qual = size; /* XXX */ +} + +/* + * Return a class suitable for a specific type. + */ +int +gclass(TWORD t) +{ + return (szty(t) == 2 ? CLASSB : CLASSA); +} + +/* + * For class c, find worst-case displacement of the number of + * registers in the array r[] indexed by class. + */ +int +COLORMAP(int c, int *r) +{ + int num; + + switch (c) { + case CLASSA: + /* there are 12 classa, so min 6 classb are needed to block */ + num = r[CLASSB] * 2; + num += r[CLASSA]; + return num < 12; + case CLASSB: + /* 6 classa may block all classb */ + num = r[CLASSB] + r[CLASSA]; + return num < 6; + } + comperr("COLORMAP"); + return 0; /* XXX gcc */ +} + +/* + * Special shapes. + */ +int +special(NODE *p, int shape) +{ + return SRNOPE; +} + +/* + * Target-dependent command-line options. + */ +void +mflags(char *str) +{ +} +/* + * Do something target-dependent for xasm arguments. + * Supposed to find target-specific constraints and rewrite them. + */ +int +myxasm(struct interpass *ip, NODE *p) +{ + return 0; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/vax/macdefs.h b/compilers/pcc/pcc-1.0.0/arch/vax/macdefs.h new file mode 100644 index 00000000..29f3307e --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/vax/macdefs.h @@ -0,0 +1,259 @@ +/* $Id: macdefs.h,v 1.5 2009/01/24 21:43:49 gmcgarry Exp $ */ +/* + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code and documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditionsand the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +# define makecc(val,i) lastcon = (lastcon<<8)|((val<<24)>>24); + +# define ARGINIT 32 +# define AUTOINIT 0 +# define SZCHAR 8 +# define SZBOOL 8 +# define SZINT 32 +# define SZFLOAT 32 +# define SZDOUBLE 64 +# define SZLDOUBLE 64 /* XXX use longer? */ +# define SZLONG 32 +# define SZLONGLONG 64 +# define SZSHORT 16 +# define SZPOINT(t) 32 +# define ALCHAR 8 +# define ALBOOL 8 +# define ALINT 32 +# define ALFLOAT 32 +# define ALDOUBLE 32 +# define ALLDOUBLE 32 +# define ALLONG 32 +# define ALLONGLONG 32 +# define ALSHORT 16 +# define ALPOINT 32 +# define ALSTRUCT 8 +# define ALSTACK 32 + +/* + * Min/max values. + */ +#define MIN_CHAR -128 +#define MAX_CHAR 127 +#define MAX_UCHAR 255 +#define MIN_SHORT -32768 +#define MAX_SHORT 32767 +#define MAX_USHORT 65535 +#define MIN_INT (-0x7fffffff-1) +#define MAX_INT 0x7fffffff +#define MAX_UNSIGNED 0xffffffff +#define MIN_LONG MIN_INT +#define MAX_LONG MAX_INT +#define MAX_ULONG MAX_UNSIGNED +#define MIN_LONGLONG 0x8000000000000000LL +#define MAX_LONGLONG 0x7fffffffffffffffLL +#define MAX_ULONGLONG 0xffffffffffffffffULL + +/* Default char is signed */ +#undef CHAR_UNSIGNED +#define BOOL_TYPE CHAR /* what used to store _Bool */ + +/* size in which constants are converted */ +/* should be long if feasable */ + +typedef long long CONSZ; +typedef unsigned long long U_CONSZ; + +# define CONFMT "%lld" +# define LABFMT ".L%d" +# define STABLBL ".LL%d" + +/* size in which offsets are kept + * should be large enough to cover address space in bits + */ +typedef long long OFFSZ; + +/* character set macro */ + +# define CCTRANS(x) x + +/* register cookie for stack poINTer */ + +# define STKREG 13 +# define ARGREG 12 + +/* maximum and minimum register variables */ + +# define MAXRVAR 11 +# define MINRVAR 6 + +/* show stack grows negatively */ +#define BACKAUTO +#define BACKTEMP + +/* show field hardware support on VAX */ +#define FIELDOPS + +/* bytes are numbered from right to left */ +#define RTOLBYTES + +/* we want prtree included */ +# define STDPRTREE +# ifndef FORT +# define ONEPASS +#endif + +# define ENUMSIZE(high,low) INT + +/* VAX-11/780 Registers */ + + /* scratch registers */ +# define R0 0 +# define R1 1 +# define R2 2 +# define R3 3 +# define R4 4 +# define R5 5 + + /* register variables */ +# define R6 6 +# define R7 7 +# define R8 8 +# define R9 9 +# define R10 10 +# define R11 11 + + /* special purpose */ +# define AP 12 /* argument pointer */ +# define FP 13 /* frame pointer */ +# define SP 14 /* stack pointer */ +# define PC 15 /* program counter */ + + /* floating registers */ + + /* there are no floating point registers on the VAX */ + /* but there are concatenated regs */ + /* we call them XR? */ +#define XR0 16 +#define XR1 17 +#define XR2 18 +#define XR3 19 +#define XR4 20 +#define XR5 21 +#define XR6 22 +#define XR7 23 +#define XR8 24 +#define XR9 25 +#define XR10 26 + + + + +extern int fregs; +extern int maxargs; + +# define BYTEOFF(x) ((x)&03) +# define wdal(k) (BYTEOFF(k)==0) +# define BITOOR(x) ((x)>>3) /* bit offset to oreg offset */ + +# define REGSZ 16 + +# define TMPREG FP + +//# define R2REGS /* permit double indexing */ + +# define STOARG(p) /* just evaluate the arguments, and be done with it... */ +# define STOFARG(p) +# define STOSTARG(p) +# define genfcall(a,b) gencall(a,b) + +# define NESTCALL + +/* + * Register allocator stuff. + * The register allocator sees this as 16 general regs (AREGs) + * and 11 64-bit concatenated regs. (BREGs) + */ +#define MAXREGS 033 /* 27 registers */ + +#define RSTATUS \ + SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, \ + SAREG|TEMPREG, SAREG|TEMPREG, SAREG|PERMREG, SAREG|PERMREG, \ + SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, SAREG|PERMREG, \ + 0, 0, 0, 0, /* do not care about ap, fp, sp or pc */ \ + SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \ + SBREG, SBREG, SBREG, + +#define ROVERLAP \ + { XR0, -1 }, \ + { XR0, XR1, -1 }, \ + { XR1, XR2, -1 }, \ + { XR2, XR3, -1 }, \ + { XR3, XR4, -1 }, \ + { XR4, XR5, -1 }, \ + { XR5, XR6, -1 }, \ + { XR6, XR7, -1 }, \ + { XR7, XR8, -1 }, \ + { XR8, XR9, -1 }, \ + { XR9, XR10, -1 }, \ + { XR10, -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { -1 }, \ + { R0, R1, XR1, -1 }, \ + { R1, R2, XR0, XR2, -1 }, \ + { R2, R3, XR1, XR3, -1 }, \ + { R3, R4, XR2, XR4, -1 }, \ + { R4, R5, XR3, XR5, -1 }, \ + { R5, R6, XR4, XR6, -1 }, \ + { R6, R7, XR5, XR7, -1 }, \ + { R7, R8, XR6, XR8, -1 }, \ + { R8, R9, XR7, XR9, -1 }, \ + { R9, R10, XR8, XR10, -1 }, \ + { R10, R11, XR9, -1 }, + +#define NUMCLASS 2 /* highest number of reg classes used */ + +/* size, in registers, needed to hold thing of type t */ +#define szty(t) (((t) == DOUBLE || (t) == LDOUBLE || (t) == FLOAT || \ + (t) == LONGLONG || (t) == ULONGLONG) ? 2 : 1) +#define FPREG FP /* frame pointer */ + +#define DECRA(x,y) (((x) >> (y*6)) & 63) /* decode encoded regs */ +#define ENCRD(x) (x) /* Encode dest reg in n_reg */ +#define ENCRA1(x) ((x) << 6) /* A1 */ +#define ENCRA2(x) ((x) << 12) /* A2 */ +#define ENCRA(x,y) ((x) << (6+y*6)) /* encode regs in int */ + +#define PCLASS(p) (szty(p->n_type) == 2 ? SBREG : SAREG) +#define RETREG(x) (szty(x) == 2 ? XR0 : R0) +#define GCLASS(x) (x < XR0 ? CLASSA : CLASSB) +int COLORMAP(int c, int *r); + +#define SNCON (MAXSPECIAL+1) /* named constand */ diff --git a/compilers/pcc/pcc-1.0.0/arch/vax/order.c b/compilers/pcc/pcc-1.0.0/arch/vax/order.c new file mode 100644 index 00000000..aef21fe1 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/vax/order.c @@ -0,0 +1,611 @@ +/* $Id: order.c,v 1.4 2007/11/26 00:10:03 gmcgarry Exp $ */ +/* + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code and documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditionsand the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +# include "pass2.h" + +int canaddr(NODE *); + +int maxargs = { -1 }; + +#if 0 +stoasg( p, o ) register NODE *p; { + /* should the assignment op p be stored, + given that it lies as the right operand of o + (or the left, if o==UNARY MUL) */ +/* + if( p->op == INCR || p->op == DECR ) return; + if( o==UNARY MUL && p->left->op == REG && !isbreg(p->left->rval) ) SETSTO(p,INAREG); + */ + } +#endif + +int +deltest( p ) register NODE *p; { + /* should we delay the INCR or DECR operation p */ + p = p->n_left; + return( p->n_op == REG || p->n_op == NAME || p->n_op == OREG ); + } + +#if 0 +autoincr( p ) NODE *p; { + register NODE *q = p->left, *r; + + if( q->op == INCR && (r=q->left)->op == REG && + ISPTR(q->type) && p->type == DECREF(q->type) && + tlen(p) == q->right->lval ) return(1); + + return(0); + } + +mkadrs(p) register NODE *p; { + register o; + + o = p->op; + + if( asgop(o) ){ + if( p->left->su >= p->right->su ){ + if( p->left->op == UNARY MUL ){ + SETSTO( p->left->left, INTEMP ); + } + else if( p->left->op == FLD && p->left->left->op == UNARY MUL ){ + SETSTO( p->left->left->left, INTEMP ); + } + else { /* should be only structure assignment */ + SETSTO( p->left, INTEMP ); + } + } + else SETSTO( p->right, INTEMP ); + } + else { + if( p->left->su > p->right->su ){ + SETSTO( p->left, INTEMP ); + } + else { + SETSTO( p->right, INTEMP ); + } + } + } +#endif + +int +notoff(TWORD t, int r, CONSZ off, char *cp) +{ + /* is it legal to make an OREG or NAME entry which has an + * offset of off, (from a register of r), if the + * resulting thing had type t */ + +/* if( r == R0 ) return( 1 ); / * NO */ + return(0); /* YES */ + } + +# define max(x,y) ((x)<(y)?(y):(x)) + +#if 0 +sucomp( p ) register NODE *p; { + + /* set the su field in the node to the sethi-ullman + number, or local equivalent */ + + register o, ty, sul, sur, r; + + o = p->op; + ty = optype( o ); + p->su = szty( p->type ); /* 2 for float or double, else 1 */; + + if( ty == LTYPE ){ + if( o == OREG ){ + r = p->rval; + /* oreg cost is (worst case) 1 + number of temp registers used */ + if( R2TEST(r) ){ + if( R2UPK1(r)!=100 && istreg(R2UPK1(r)) ) ++p->su; + if( istreg(R2UPK2(r)) ) ++p->su; + } + else { + if( istreg( r ) ) ++p->su; + } + } + if( p->su == szty(p->type) && + (p->op!=REG || !istreg(p->rval)) && + (p->type==INT || p->type==UNSIGNED || p->type==DOUBLE) ) + p->su = 0; + return; + } + + else if( ty == UTYPE ){ + switch( o ) { + case UNARY CALL: + case UNARY STCALL: + p->su = fregs; /* all regs needed */ + return; + + default: + p->su = p->left->su + (szty( p->type ) > 1 ? 2 : 0) ; + return; + } + } + + + /* If rhs needs n, lhs needs m, regular su computation */ + + sul = p->left->su; + sur = p->right->su; + + if( o == ASSIGN ){ + /* computed by doing right, then left (if not in mem), then doing it */ + p->su = max(sur,sul+1); + return; + } + + if( o == CALL || o == STCALL ){ + /* in effect, takes all free registers */ + p->su = fregs; + return; + } + + if( o == STASG ){ + /* right, then left */ + p->su = max( max( 1+sul, sur), fregs ); + return; + } + + if( asgop(o) ){ + /* computed by doing right, doing left address, doing left, op, and store */ + p->su = max(sur,sul+2); +/* + if( o==ASG MUL || o==ASG DIV || o==ASG MOD) p->su = max(p->su,fregs); + */ + return; + } + + switch( o ){ + case ANDAND: + case OROR: + case QUEST: + case COLON: + case COMOP: + p->su = max( max(sul,sur), 1); + return; + + case PLUS: + case OR: + case ER: + /* commutative ops; put harder on left */ + if( p->right->su > p->left->su && !istnode(p->left) ){ + register NODE *temp; + temp = p->left; + p->left = p->right; + p->right = temp; + } + break; + } + + /* binary op, computed by left, then right, then do op */ + p->su = max(sul,szty(p->right->type)+sur); +/* + if( o==MUL||o==DIV||o==MOD) p->su = max(p->su,fregs); + */ + + } + +int radebug = 0; + +rallo( p, down ) NODE *p; { + /* do register allocation */ + register o, type, down1, down2, ty; + + if( radebug ) printf( "rallo( %o, %d )\n", p, down ); + + down2 = NOPREF; + p->rall = down; + down1 = ( down &= ~MUSTDO ); + + ty = optype( o = p->op ); + type = p->type; + + + if( type == DOUBLE || type == FLOAT ){ + if( o == FORCE ) down1 = R0|MUSTDO; + } + else switch( o ) { + case ASSIGN: + down1 = NOPREF; + down2 = down; + break; + +/* + case MUL: + case DIV: + case MOD: + down1 = R3|MUSTDO; + down2 = R5|MUSTDO; + break; + + case ASG MUL: + case ASG DIV: + case ASG MOD: + p->left->rall = down1 = R3|MUSTDO; + if( p->left->op == UNARY MUL ){ + rallo( p->left->left, R4|MUSTDO ); + } + else if( p->left->op == FLD && p->left->left->op == UNARY MUL ){ + rallo( p->left->left->left, R4|MUSTDO ); + } + else rallo( p->left, R3|MUSTDO ); + rallo( p->right, R5|MUSTDO ); + return; + */ + + case CALL: + case STASG: + case EQ: + case NE: + case GT: + case GE: + case LT: + case LE: + case NOT: + case ANDAND: + case OROR: + down1 = NOPREF; + break; + + case FORCE: + down1 = R0|MUSTDO; + break; + + } + + if( ty != LTYPE ) rallo( p->left, down1 ); + if( ty == BITYPE ) rallo( p->right, down2 ); + + } +#endif + +void +offstar( p, s ) register NODE *p; { +comperr("offstar"); +#if 0 + if( p->n_op == PLUS ) { + if( p->n_left->n_su == fregs ) { + order( p->n_left, INAREG ); + return; + } else if( p->n_right->n_su == fregs ) { + order( p->n_right, INAREG ); + return; + } + if( p->n_left->n_op==LS && + (p->n_left->n_left->n_op!=REG || tlen(p->n_left->n_left)!=sizeof(int) ) ) { + order( p->n_left->n_left, INAREG ); + return; + } + if( p->n_right->n_op==LS && + (p->n_right->n_left->n_op!=REG || tlen(p->n_right->n_left)!=sizeof(int) ) ) { + order( p->n_right->n_left, INAREG ); + return; + } + if( p->n_type == (PTR|CHAR) || p->n_type == (PTR|UCHAR) ) { + if( p->n_left->n_op!=REG || tlen(p->n_left)!=sizeof(int) ) { + order( p->n_left, INAREG ); + return; + } + else if( p->n_right->n_op!=REG || tlen(p->n_right)!=sizeof(int) ) { + order(p->n_right, INAREG); + return; + } + } + } + if( p->n_op == PLUS || p->n_op == MINUS ){ + if( p->n_right->n_op == ICON ){ + p = p->n_left; + order( p , INAREG); + return; + } + } + + if( p->n_op == UMUL && !canaddr(p) ) { + offstar( p->n_left, 0 ); + return; + } + + order( p, INAREG ); +#endif + } + +int +setbin( p ) register NODE *p; { + +#if 0 + register int ro, rt; + + rt = p->n_right->n_type; + ro = p->n_right->n_op; + + if( canaddr( p->n_left ) && !canaddr( p->n_right ) ) { /* address rhs */ + if( ro == UMUL ) { + offstar( p->n_right->n_left, 0 ); + return(1); + } else { + order( p->n_right, INAREG|SOREG ); + return(1); + } + } + if( !istnode( p->n_left) ) { /* try putting LHS into a reg */ +/* order( p->n_left, logop(p->n_op)?(INAREG|INBREG|INTAREG|INTBREG|SOREG):(INTAREG|INTBREG|SOREG) );*/ + order( p->n_left, INAREG|INTAREG|INBREG|INTBREG|SOREG ); + return(1); + } + else if( ro == UNARY MUL && rt != CHAR && rt != UCHAR ){ + offstar( p->n_right->n_left ); + return(1); + } + else if( rt == CHAR || rt == UCHAR || rt == SHORT || rt == USHORT || (ro != REG && + ro != NAME && ro != OREG && ro != ICON ) ){ + order( p->n_right, INAREG|INBREG ); + return(1); + } +/* + else if( logop(p->n_op) && rt==USHORT ){ / * must get rhs into register */ +/* + order( p->n_right, INAREG ); + return( 1 ); + } + */ +#endif + return(0); + } + +#if 0 +int +setstr( p ) register NODE *p; { /* structure assignment */ + if( p->right->op != REG ){ + order( p->right, INTAREG ); + return(1); + } + p = p->left; + if( p->op != NAME && p->op != OREG ){ + if( p->op != UNARY MUL ) cerror( "bad setstr" ); + order( p->left, INTAREG ); + return( 1 ); + } + return( 0 ); + } +#endif + +int +setasg( p, s ) register NODE *p; { + +#if 0 + /* setup for assignment operator */ + + if( !canaddr(p->n_right) ) { + if( p->n_right->n_op == UNARY MUL ) + offstar(p->n_right->n_left); + else + order( p->n_right, INAREG|INBREG|SOREG ); + return(1); + } + if( p->n_left->n_op == UMUL ) { + offstar( p->n_left->n_left ); + return(1); + } + if( p->left->op == FLD && p->left->left->op == UNARY MUL ){ + offstar( p->left->left->left ); + return(1); + } +/* FLD patch */ + if( p->left->op == FLD && !(p->right->type==INT || p->right->type==UNSIGNED)) { + order( p->right, INAREG); + return(1); + } +/* end of FLD patch */ +#endif + return(0); + } + +/* setup for unary operator */ +int +setuni(NODE *p, int cookie) +{ + return 0; +} + + +#if 0 +int +setasop( p ) register NODE *p; { + /* setup for =ops */ + register rt, ro; + + rt = p->right->type; + ro = p->right->op; + + if( ro == UNARY MUL && rt != CHAR ){ + offstar( p->right->left ); + return(1); + } + if( ( rt == CHAR || rt == SHORT || rt == UCHAR || rt == USHORT || + ( ro != REG && ro != ICON && ro != NAME && ro != OREG ) ) ){ + order( p->right, INAREG|INBREG ); + return(1); + } +/* + if( (p->op == ASG LS || p->op == ASG RS) && ro != ICON && ro != REG ){ + order( p->right, INAREG ); + return(1); + } + */ + + + p = p->left; + if( p->op == FLD ) p = p->left; + + switch( p->op ){ + + case REG: + case ICON: + case NAME: + case OREG: + return(0); + + case UNARY MUL: + if( p->left->op==OREG ) + return(0); + else + offstar( p->left ); + return(1); + + } + cerror( "illegal setasop" ); + } +#endif + +void +deflab(int l) +{ + printf(LABFMT ":\n", l); +} + +#if 0 +genargs( p, ptemp ) register NODE *p, *ptemp; { + register NODE *pasg; + register align; + register size; + register TWORD type; + + /* generate code for the arguments */ + + /* first, do the arguments on the right */ + while( p->op == CM ){ + genargs( p->right, ptemp ); + p->op = FREE; + p = p->left; + } + + if( p->op == STARG ){ /* structure valued argument */ + + size = p->stsize; + align = p->stalign; + + /* ptemp->lval = (ptemp->lval/align)*align; / * SETOFF for negative numbers */ + ptemp->lval = 0; /* all moves to (sp) */ + + p->op = STASG; + p->right = p->left; + p->left = tcopy( ptemp ); + + /* the following line is done only with the knowledge + that it will be undone by the STASG node, with the + offset (lval) field retained */ + + if( p->right->op == OREG ) p->right->op = REG; /* only for temporaries */ + + order( p, FORARG ); + ptemp->lval += size; + return; + } + + /* ordinary case */ + + order( p, FORARG ); + } + +argsize( p ) register NODE *p; { + register t; + t = 0; + if( p->op == CM ){ + t = argsize( p->left ); + p = p->right; + } + if( p->type == DOUBLE || p->type == FLOAT ){ + SETOFF( t, 4 ); + return( t+8 ); + } + else if( p->op == STARG ){ + SETOFF( t, 4 ); /* alignment */ + return( t + ((p->stsize+3)/4)*4 ); /* size */ + } + else { + SETOFF( t, 4 ); + return( t+4 ); + } + } +#endif + +/* + * Special handling of some instruction register allocation. + */ +struct rspecial * +nspecial(struct optab *q) +{ + comperr("nspecial"); + return NULL; +} + +/* + * Set evaluation order of a binary node if it differs from default. + */ +int +setorder(NODE *p) +{ + return 0; /* nothing differs on vax */ +} + +/* + * Do the actual conversion of offstar-found OREGs into real OREGs. + */ +void +myormake(NODE *q) +{ +} +/* + * Set registers "live" at function calls (like arguments in registers). + * This is for liveness analysis of registers. + */ +int * +livecall(NODE *p) +{ + static int r[1] = { -1 }; /* Terminate with -1 */ + + return &r[0]; +} + +/* + * Signal whether the instruction is acceptable for this target. + */ +int +acceptable(struct optab *op) +{ + return 1; +} diff --git a/compilers/pcc/pcc-1.0.0/arch/vax/table.c b/compilers/pcc/pcc-1.0.0/arch/vax/table.c new file mode 100644 index 00000000..54ea9ba3 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/arch/vax/table.c @@ -0,0 +1,695 @@ +/* $Id: table.c,v 1.3 2007/10/29 14:20:22 ragge Exp $ */ +/* + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code and documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditionsand the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +# include "pass2.h" + +# define WPTR TPTRTO|TINT|TLONG|TFLOAT|TDOUBLE|TPOINT|TUNSIGNED|TULONG +# define AWD SNAME|SOREG|SCON|STARNM|STARREG +/* tbl */ +# define ANYSIGNED TPOINT|TINT|TLONG|TSHORT|TCHAR +# define ANYUSIGNED TUNSIGNED|TULONG|TUSHORT|TUCHAR +# define ANYFIXED ANYSIGNED|ANYUSIGNED +# define TWORD TINT|TUNSIGNED|TPOINT|TLONG|TULONG +/* tbl */ +# define TBREG TLONGLONG|TULONGLONG|TDOUBLE + +struct optab table[] = { +/* First entry must be an empty entry */ +{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", }, + +{ PCONV, INAREG|INAREG, + SAREG|AWD, TCHAR|TSHORT, + SANY, TPOINT, + NAREG|NASL, RESC1, + " cvtZLl AL,A1\n", }, + +{ PCONV, INAREG|INAREG, + SAREG|AWD, TUCHAR|TUSHORT, + SANY, TPOINT, + NAREG|NASL, RESC1, + " movzZLl AL,A1\n", }, + +{ SCONV, INBREG|FORCC, + SAREG, TDOUBLE, + SANY, TDOUBLE, + 0, RLEFT, + "", }, + +{ SCONV, INBREG|FORCC, + SAREG|AWD, TANY, + SANY, TFLOAT|TDOUBLE, + NAREG|NASL, RESC1|RESCC, + " cvtZLd AL,A1\n", }, + +{ SCONV, INAREG|FORCC, + SAREG|AWD, TFLOAT|TDOUBLE, + SANY, ANYFIXED, + NAREG|NASL, RESC1|RESCC, + " cvtZLZF AL,A1\n", }, + +{ SCONV, INAREG|FORCC, + SAREG|SNAME|SCON|STARNM, TANY, + SANY, ANYUSIGNED, + NAREG|NASL, RESC1|RESCC, + " movzZRl AL,A1\n", }, + +{ SCONV, INAREG|FORCC, + SSOREG, TANY, + SANY, ANYUSIGNED, + NAREG|NASL, RESC1|RESCC, + " movzZRl AL,A1\n", }, + +{ SCONV, INAREG|FORCC, + SAREG|SNAME|SCON|STARNM, TANY, + SANY, TANY, + NAREG|NASL, RESC1|RESCC, + " cvtZRl AL,A1\n", }, + +{ SCONV, INAREG|FORCC, + SSOREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1|RESCC, + " cvtZRl AL,A1\n", }, + +{ GOTO, FOREFF, + SCON, TANY, + SANY, TANY, + 0, RNOP, + " ZJ\n", }, + +{ GOTO, FOREFF, + SAREG, TANY, + SANY, TANY, + 0, RNOP, + " jmp (AL)\n", }, + +{ STARG, INTEMP, + SCON|SAREG, TANY, + SANY, TANY, + NTEMP+2*NAREG, RESC3, + "ZS", }, + +#if 0 +{ STASG, FORARG, + SNAME|SOREG, TANY, + SCON|SAREG, TANY, + 0, RNULL, + " subl2 ZT,sp\nZS", }, +#endif + +{ ADDROF, INAREG, + SNAME, TANY, + SAREG, TANY, + NAREG, RESC1, + " movab AL,A1\n", }, + +{ STASG, FOREFF, + SNAME|SOREG, TANY, + SCON|SAREG, TANY, + 0, RNOP, + "ZS", }, + +{ STASG, INAREG, + SNAME|SOREG, TANY, + SCON, TANY, + NAREG, RESC1, + "ZS movl AR,A1\n", }, + +{ STASG, INAREG, + SNAME|SOREG, TANY, + SAREG, TANY, + 0, RRIGHT, + " pushl AR\nZS movl (sp)+,AR\n", }, + +{ FLD, INAREG|INAREG, + SANY, TANY, + SFLD, ANYSIGNED, + NAREG|NASR, RESC1, + " extv H,S,AR,A1\n", }, + +{ FLD, INAREG|INAREG, + SANY, TANY, + SFLD, ANYUSIGNED, + NAREG|NASR, RESC1, + " extzv H,S,AR,A1\n", }, + +#if 0 +{ FLD, FORARG, + SANY, TANY, + SFLD, ANYSIGNED, + 0, RNULL, + " extv H,S,AR,-(sp)\n", }, + +{ FLD, FORARG, + SANY, TANY, + SFLD, ANYUSIGNED, + 0, RNULL, + " extzv H,S,AR,-(sp)\n", }, +#endif + +{ OPLOG, FORCC, + SAREG|AWD, TWORD, + SAREG|AWD, TWORD, + 0, RESCC, + " cmpl AL,AR\n", }, + +{ OPLOG, FORCC, + SAREG|AWD, TSHORT|TUSHORT, + SAREG|AWD, TSHORT|TUSHORT, + 0, RESCC, + " cmpw AL,AR\n", }, + +{ OPLOG, FORCC, + SAREG|AWD, TCHAR|TUCHAR, + SAREG|AWD, TCHAR|TUCHAR, + 0, RESCC, + " cmpb AL,AR\n", }, + +{ OPLOG, FORCC, + SAREG|AWD, TSHORT|TUSHORT, + SSCON, TANY, + 0, RESCC, + " cmpw AL,AR\n", }, + +{ OPLOG, FORCC, + SAREG|AWD, TCHAR|TUCHAR, + SCCON, TANY, + 0, RESCC, + " cmpb AL,AR\n", }, + +{ OPLOG, FORCC, + SAREG|AWD, TDOUBLE, + SAREG|AWD, TDOUBLE, + 0, RESCC, + " cmpd AL,AR\n", }, + +{ OPLOG, FORCC, + SAREG|AWD, TFLOAT|TDOUBLE, + SAREG|AWD, TFLOAT|TDOUBLE, + 0, RESCC, + " cmpf AL,AR\n", }, + +{ CCODES, INAREG|INAREG, + SANY, TANY, + SANY, TANY, + NAREG, RESC1, + " movl $1,A1\nZN", }, + +/* + * Subroutine calls. + */ + +{ CALL, FOREFF, + SCON, TANY, + SANY, TANY, + 0, 0, + " calls ZC,CL\n", }, + +{ UCALL, FOREFF, + SCON, TANY, + SANY, TANY, + 0, 0, + " calls $0,CL\n", }, + +{ CALL, INAREG, + SCON, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be register 0 */ + " calls ZC,CL\n", }, + +{ UCALL, INAREG, + SCON, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be register 0 */ + " calls $0,CL\n", }, + +{ CALL, INAREG|FOREFF, + SAREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* should be 0 */ + " calls ZC,(AL)\n", }, + +{ UCALL, INAREG|FOREFF, + SAREG, TANY, + SANY, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT|TFLOAT|TDOUBLE, + NAREG|NASL, RESC1, /* should be 0 */ + " calls ZC,(AL)\n", }, + +{ UCALL, INAREG|FOREFF, + SNAME, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* really reg 0 */ + " calls ZC,*AL\n", }, + +{ UCALL, INAREG|FOREFF, + SSOREG, TANY, + SANY, TANY, + NAREG|NASL, RESC1, /* really reg 0 */ + " calls ZC,*AL\n", }, + +/* + * Function arguments + */ +{ FUNARG, FOREFF, + SCON|SAREG|SNAME|SOREG, TWORD|TPOINT, + SANY, TWORD|TPOINT, + 0, RNULL, + " pushl AL\n" }, + +#if 0 +{ ASG RS, INAREG|FOREFF|FORCC, + SAREG, TWORD, + SCON, TINT, + 0, RLEFT|RESCC, + " extzv AR,ZU,AL,AL\n", }, + +{ ASG RS, INAREG|FOREFF|FORCC, + SAREG, TWORD, + SAREG, ANYFIXED, + NAREG, RLEFT|RESCC, + " subl3 AR,$32,A1\n extzv AR,A1,AL,AL\n", }, + +{ ASG RS, INAREG|FOREFF|FORCC, + SAREG, TWORD, + SAREG|AWD, TWORD, + NAREG, RLEFT|RESCC, + " subl3 AR,$32,A1\n extzv AR,A1,AL,AL\n", }, +#endif + +{ RS, INAREG|INAREG|FORCC, + SAREG, TWORD, + SCON, TINT, + NAREG|NASL, RESC1|RESCC, + " extzv AR,ZU,AL,A1\n", }, + +#if 0 +{ ASG LS, INAREG|FOREFF|FORCC, + SAREG|AWD, TWORD, + SAREG|AWD, ANYSIGNED|ANYUSIGNED, + 0, RLEFT|RESCC, + " ashl AR,AL,AL\n", }, +#endif + +{ LS, INAREG|INAREG|FORCC, + SAREG|AWD, TWORD, + SAREG|AWD, ANYSIGNED|ANYUSIGNED, + NAREG|NASL|NASR, RESC1|RESCC, + " ashl AR,AL,A1\n", }, + +#if 0 +{ INCR, FOREFF, + SAREG|AWD, TANY, + SANY, TANY, + 0, RLEFT, + " ZE\n", }, + +{ DECR, FOREFF, + SAREG|AWD, TANY, + SCON, TANY, + 0, RLEFT, + " ZE\n", }, + +{ INCR, INAREG|INAREG, + SAREG|AWD, TANY, + SCON, TANY, + NAREG, RESC1, + " ZD\n", }, + +{ DECR, INAREG|INAREG, + SAREG|AWD, TANY, + SCON, TANY, + NAREG, RESC1, + " ZD\n", }, +#endif + +{ ASSIGN, INBREG|FOREFF, + SBREG|AWD, TBREG, + SBREG|AWD, TBREG, + 0, RDEST, + " movq AR,AL\n", }, + +{ ASSIGN, INAREG|FOREFF|FORCC, + SAREG|AWD, TANY, + SAREG|AWD, TANY, + 0, RDEST|RESCC, + " ZA\n", }, + +{ ASSIGN, INAREG|FOREFF|FORCC, + SFLD, TANY, + SAREG|AWD, TWORD, + 0, RDEST|RESCC, + " insv AR,H,S,AL\n", }, + +{ ASSIGN, INAREG|FOREFF|FORCC, + SAREG|AWD, TWORD, + SFLD, ANYSIGNED, + 0, RDEST|RESCC, + " extv H,S,AR,AL\n", }, + +{ ASSIGN, INAREG|FOREFF|FORCC, + SAREG|AWD, TWORD, + SFLD, ANYUSIGNED, + 0, RDEST|RESCC, + " extzv H,S,AR,AL\n", }, + +/* dummy UNARY MUL entry to get U* to possibly match OPLTYPE */ +{ UMUL, FOREFF, + SCC, TANY, + SCC, TANY, + 0, RNULL, + " HELP HELP HELP\n", }, + +#if 0 +{ REG, FORARG, + SANY, TANY, + SAREG, TDOUBLE|TFLOAT, + 0, RNULL, + " movZR AR,-(sp)\n", }, +#endif + +{ REG, INTEMP, + SANY, TANY, + SAREG, TDOUBLE, + 2*NTEMP, RESC1, + " movd AR,A1\n", }, + +{ REG, INTEMP, + SANY, TANY, + SAREG, TANY, + NTEMP, RESC1, + " movZF AR,A1\n", }, + +{ OPLEAF, FOREFF, + SANY, TANY, + SAREG|AWD, TANY, + 0, RLEFT, + "", }, + +{ OPLTYPE, INAREG|INAREG, + SANY, TANY, + SANY, TFLOAT|TDOUBLE, + 2*NAREG|NASR, RESC1, + " ZA\n", }, + +{ OPLTYPE, INAREG|INAREG, + SANY, TANY, + SANY, TANY, + NAREG|NASR, RESC1, + " ZA\n", }, + +{ OPLTYPE, FORCC, + SANY, TANY, + SANY, TANY, + 0, RESCC, + " tstZR AR\n", }, + +#if 0 +{ OPLTYPE, FORARG, + SANY, TANY, + SANY, TWORD, + 0, RNULL, + " pushl AR\n", }, + +{ OPLTYPE, FORARG, + SANY, TANY, + SANY, TCHAR|TSHORT, + 0, RNULL, + " cvtZRl AR,-(sp)\n", }, + +{ OPLTYPE, FORARG, + SANY, TANY, + SANY, TUCHAR|TUSHORT, + 0, RNULL, + " movzZRl AR,-(sp)\n", }, + +{ OPLTYPE, FORARG, + SANY, TANY, + SANY, TDOUBLE, + 0, RNULL, + " movd AR,-(sp)\n", }, + +{ OPLTYPE, FORARG, + SANY, TANY, + SANY, TFLOAT, + 0, RNULL, + " cvtfd AR,-(sp)\n", }, +#endif + +{ UMINUS, INAREG|FORCC, + SAREG|AWD, TINT|TUNSIGNED|TLONG|TULONG|TDOUBLE, + SANY, TANY, + NAREG|NASL, RESC1|RESCC, + " mnegZL AL,A1\n", }, + +{ COMPL, INAREG|FORCC, + SAREG|AWD, TINT|TUNSIGNED, + SANY, TANY, + NAREG|NASL, RESC1|RESCC, + " mcomZL AL,A1\n", }, + +{ COMPL, INAREG|FORCC, + SAREG|AWD, ANYSIGNED|ANYUSIGNED, + SANY, TANY, + NAREG|NASL, RESC1|RESCC, + " cvtZLl AL,A1\n mcoml A1,A1\n", }, + +{ AND, FORCC, + SAREG|AWD, TWORD, + SCON, TWORD, + 0, RESCC, + " bitl ZZ,AL\n", }, + +{ AND, FORCC, + SAREG|AWD, TSHORT|TUSHORT, + SSCON, TWORD, + 0, RESCC, + " bitw ZZ,AL\n", }, + +{ AND, FORCC, + SAREG|AWD, TCHAR|TUCHAR, + SCCON, TWORD, + 0, RESCC, + " bitb ZZ,AL\n", }, + +#if 0 +{ ASG AND, INAREG|FOREFF|FORCC, + SAREG, ANYFIXED, + SCON, TWORD, + 0, RLEFT|RESCC, + " bicl2 AR,AL\n", }, + +{ ASG OPMUL, INAREG|FOREFF|FORCC, + SAREG|AWD, TINT|TUNSIGNED|TLONG|TULONG, + SAREG|AWD, TINT|TUNSIGNED|TLONG|TULONG, + 0, RLEFT|RESCC, + " OL2 AR,AL\n", }, +#endif + +{ OPMUL, INAREG|INAREG|FORCC, + SAREG, TINT|TUNSIGNED|TLONG|TULONG, + SAREG|AWD, TINT|TUNSIGNED|TLONG|TULONG, + 0, RLEFT|RESCC, + " OL2 AR,AL\n", }, + +{ OPMUL, INAREG|INAREG|FORCC, + SAREG|AWD, TINT|TUNSIGNED|TLONG|TULONG, + SAREG|AWD, TINT|TUNSIGNED|TLONG|TULONG, + NAREG|NASL|NASR, RESC1|RESCC, + " OL3 AR,AL,A1\n", }, + +#if 0 +{ ASG MOD, INAREG|INAREG|FOREFF|FORCC, + SAREG, TINT|TUNSIGNED|TLONG|TULONG, + SAREG|AWD, TINT|TUNSIGNED|TLONG|TULONG, + NAREG, RLEFT|RESCC, + " divl3 AR,AL,A1\n mull2 AR,A1\n subl2 A1,AL\n", }, +#endif + +{ MOD, INAREG|INAREG, + SAREG|AWD, TINT|TUNSIGNED|TLONG|TULONG, + SAREG|AWD, TINT|TUNSIGNED|TLONG|TULONG, + NAREG, RESC1, + " divl3 AR,AL,A1\n mull2 AR,A1\n subl3 A1,AL,A1\n", }, + +#if 0 +{ ASG PLUS, INAREG|FOREFF|FORCC, + SAREG|AWD, ANYSIGNED|ANYUSIGNED, + SONE, TINT|TLONG, + 0, RLEFT|RESCC, + " incZL AL\n", }, + +{ ASG MINUS, INAREG|FOREFF|FORCC, + SAREG|AWD, ANYSIGNED|ANYUSIGNED, + SONE, TINT|TLONG, + 0, RLEFT|RESCC, + " decZL AL\n", }, +#endif + +{ PLUS, INAREG|INAREG|FORCC, + SAREG, ANYFIXED, + SONE, TWORD, + 0, RLEFT|RESCC, + " incZL AL\n", }, + +{ MINUS, INAREG|INAREG|FORCC, + SAREG, ANYFIXED, + SONE, TWORD, + 0, RLEFT|RESCC, + " decZL AL\n", }, + +#if 0 +{ ASG OPSIMP, INAREG|FOREFF|FORCC, + SAREG|AWD, TWORD, + SAREG|AWD, TWORD, + 0, RLEFT|RESCC, + " OL2 AR,AL\n", }, + +{ ASG OPSIMP, INAREG|FOREFF|FORCC, + AWD, TSHORT|TUSHORT, + SAREG|AWD, TSHORT|TUSHORT, + 0, RLEFT|RESCC, + " OW2 AR,AL\n", }, + +{ ASG OPSIMP, INAREG|FOREFF|FORCC, + AWD, TSHORT|TUSHORT, + SSCON, TWORD, + 0, RLEFT|RESCC, + " OW2 AR,AL\n", }, + +{ ASG OPSIMP, INAREG|FOREFF|FORCC, + AWD, TCHAR|TUCHAR, + SAREG|AWD, TCHAR|TUCHAR, + 0, RLEFT|RESCC, + " OB2 AR,AL\n", }, + +{ ASG OPSIMP, INAREG|FOREFF|FORCC, + AWD, TCHAR|TUCHAR, + SCCON, TWORD, + 0, RLEFT|RESCC, + " OB2 AR,AL\n", }, +#endif + +{ OPSIMP, INAREG|INAREG|FORCC, + SAREG, ANYFIXED, + SAREG|AWD, TWORD, + 0, RLEFT|RESCC, + " OL2 AR,AL\n", }, + +{ OPSIMP, INAREG|INAREG|FORCC, + SAREG|AWD, TWORD, + SAREG|AWD, TWORD, + NAREG|NASL|NASR, RESC1|RESCC, + " OL3 AR,AL,A1\n", }, + +#if 0 +{ ASG OPFLOAT, INAREG|FOREFF|FORCC, + SAREG|AWD, TDOUBLE, + SAREG|AWD, TDOUBLE, + 0, RLEFT|RESCC, + " OD2 AR,AL\n", }, + +{ ASG OPFLOAT, INAREG|FOREFF|FORCC, + SAREG|AWD, TFLOAT, + SAREG|AWD, TFLOAT, + 0, RLEFT|RESCC, + " OF2 AR,AL\n", }, + +{ ASG OPFLOAT, INAREG|FOREFF|FORCC, + SAREG|AWD, TDOUBLE, + SAREG|AWD, TFLOAT, + NAREG|NASR, RLEFT|RESCC, + " cvtfd AR,A1\n OD2 A1,AL\n", }, + +{ ASG OPFLOAT, INAREG|INAREG|FOREFF|FORCC, + SAREG|AWD, TFLOAT, + SAREG|AWD, TDOUBLE, + NAREG, RLEFT|RESC1|RESCC, + " cvtfd AL,A1\n OD2 AR,A1\n cvtdf A1,AL\n", }, +#endif + +{ OPFLOAT, INAREG|INAREG|FORCC, + SAREG, TDOUBLE, + SAREG|AWD, TDOUBLE, + 0, RLEFT|RESCC, + " OD2 AR,AL\n", }, + +{ OPFLOAT, INAREG|INAREG|FORCC, + SAREG|AWD, TDOUBLE, + SAREG|AWD, TDOUBLE, + NAREG|NASL|NASR, RESC1|RESCC, + " OD3 AR,AL,A1\n", }, + +{ OPFLOAT, INAREG|INAREG|FORCC, + SAREG|AWD, TFLOAT, + SAREG|AWD, TDOUBLE, + NAREG|NASL, RESC1|RESCC, + " cvtfd AL,A1\n OD2 AR,A1\n", }, + +{ OPFLOAT, INAREG|INAREG|FORCC, + SAREG|AWD, TDOUBLE, + SAREG|AWD, TFLOAT, + NAREG|NASR, RESC1|RESCC, + " cvtfd AR,A1\n OD3 A1,AL,A1\n", }, + +{ OPFLOAT, INAREG|INAREG|FORCC, + SAREG|AWD, TFLOAT, + SAREG|AWD, TFLOAT, + NAREG|NASL|NASR, RESC1|RESCC, + " OF3 AR,AL,A1\n cvtfd A1,A1\n", }, + + /* Default actions for hard trees ... */ + +# define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,"" + +{ UMUL, DF( UMUL ), }, + +{ ASSIGN, DF(ASSIGN), }, + +{ STASG, DF(STASG), }, + +{ OPLEAF, DF(NAME), }, + +{ OPLOG, FORCC, + SANY, TANY, + SANY, TANY, + REWRITE, BITYPE, + "", }, + +{ OPUNARY, DF(UMINUS), }, + +{ OPANY, DF(BITYPE), }, + +{ FREE, FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" } +}; diff --git a/compilers/pcc/pcc-1.0.0/cc/CVS/Entries b/compilers/pcc/pcc-1.0.0/cc/CVS/Entries new file mode 100644 index 00000000..84826e68 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/CVS/Entries @@ -0,0 +1,5 @@ +/Makefile.in/1.3/Sun Jan 6 17:18:55 2008//Tr-1-0-0-RELEASE +D/cc//// +D/ccom//// +D/cpp//// +D diff --git a/compilers/pcc/pcc-1.0.0/cc/CVS/Repository b/compilers/pcc/pcc-1.0.0/cc/CVS/Repository new file mode 100644 index 00000000..7d4959b1 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/CVS/Repository @@ -0,0 +1 @@ +pcc/cc diff --git a/compilers/pcc/pcc-1.0.0/cc/CVS/Root b/compilers/pcc/pcc-1.0.0/cc/CVS/Root new file mode 100644 index 00000000..71e2ccb9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/CVS/Root @@ -0,0 +1 @@ +/cvsroot diff --git a/compilers/pcc/pcc-1.0.0/cc/CVS/Tag b/compilers/pcc/pcc-1.0.0/cc/CVS/Tag new file mode 100644 index 00000000..060fac05 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/CVS/Tag @@ -0,0 +1 @@ +Nr-1-0-0-RELEASE diff --git a/compilers/pcc/pcc-1.0.0/cc/Makefile.in b/compilers/pcc/pcc-1.0.0/cc/Makefile.in new file mode 100644 index 00000000..c5abb1ca --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/Makefile.in @@ -0,0 +1,39 @@ +# $Id: Makefile.in,v 1.3 2008/01/06 17:18:55 ragge Exp $ +# +# Makefile.in for top-level of pcc. +# + +@SET_MAKE@ +VPATH=@srcdir@ +CC=@CC@ +CFLAGS=@CFLAGS@ +LDFLAGS=@LDFLAGS@ +CPPFLAGS=@CPPFLAGS@ +YACC=@YACC@ +LEX=@LEX@ + +SUBDIR=cc cpp ccom + +all: ${SUBDIR} + +install: + cd cc && ${MAKE} install + cd cpp && ${MAKE} install + cd ccom && ${MAKE} install + +clean: + cd cc && ${MAKE} clean + cd cpp && ${MAKE} clean + cd ccom && ${MAKE} clean + +distclean: + cd cc && ${MAKE} distclean + cd cpp && ${MAKE} distclean + cd ccom && ${MAKE} distclean + /bin/rm -rf Makefile config.log stamp-h1 config.status \ + configure.lineno config.h autom4te.cache + +${SUBDIR}: nonexistant + cd $@; $(MAKE) all $(MFLAGS) + +nonexistant: diff --git a/compilers/pcc/pcc-1.0.0/cc/cc/CVS/Entries b/compilers/pcc/pcc-1.0.0/cc/cc/CVS/Entries new file mode 100644 index 00000000..aa535467 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cc/CVS/Entries @@ -0,0 +1,4 @@ +/Makefile.in/1.22/Sat Nov 14 16:27:23 2009//Tr-1-0-0-RELEASE +/cc.1/1.16/Mon Apr 5 14:24:06 2010//Tr-1-0-0-RELEASE +/cc.c/1.170.2.1/Tue Mar 15 19:25:36 2011//Tr-1-0-0-RELEASE +D diff --git a/compilers/pcc/pcc-1.0.0/cc/cc/CVS/Repository b/compilers/pcc/pcc-1.0.0/cc/cc/CVS/Repository new file mode 100644 index 00000000..ab84bbd8 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cc/CVS/Repository @@ -0,0 +1 @@ +pcc/cc/cc diff --git a/compilers/pcc/pcc-1.0.0/cc/cc/CVS/Root b/compilers/pcc/pcc-1.0.0/cc/cc/CVS/Root new file mode 100644 index 00000000..71e2ccb9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cc/CVS/Root @@ -0,0 +1 @@ +/cvsroot diff --git a/compilers/pcc/pcc-1.0.0/cc/cc/CVS/Tag b/compilers/pcc/pcc-1.0.0/cc/cc/CVS/Tag new file mode 100644 index 00000000..060fac05 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cc/CVS/Tag @@ -0,0 +1 @@ +Nr-1-0-0-RELEASE diff --git a/compilers/pcc/pcc-1.0.0/cc/cc/Makefile.in b/compilers/pcc/pcc-1.0.0/cc/cc/Makefile.in new file mode 100644 index 00000000..5849eca5 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cc/Makefile.in @@ -0,0 +1,70 @@ +# $Id: Makefile.in,v 1.22 2009/11/14 16:27:23 ragge Exp $ +# +# Makefile.in for the cc part of pcc. +# +VPATH=@srcdir@ +srcdir=@srcdir@ +top_srcdir=@top_srcdir@ +top_builddir=@top_builddir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libdir = @libdir@ +libexecdir = @libexecdir@ +includedir = @includedir@ +datarootdir = @datarootdir@ +mandir = @mandir@ +strip = @strip@ +CC = @CC@ +EXEEXT = @EXEEXT@ +TARGOS = @targos@ +TARGMACH = @targmach@ +TARGET = @target@ +VERSION = @PACKAGE_VERSION@ +PCCLIBDIR = $(libdir)/pcc/$(TARGET)/$(VERSION)/lib +PCCINCDIR = $(libdir)/pcc/$(TARGET)/$(VERSION)/include +CFLAGS = @CFLAGS@ @ADD_CFLAGS@ +CPPFLAGS = @CPPFLAGS@ -DLIBEXECDIR=\"${libexecdir}/\" \ + @ADD_CPPFLAGS@ -DINCLUDEDIR=\"${includedir}/\" \ + -DPCCINCDIR=\"${PCCINCDIR}/\" -DPCCLIBDIR=\"${PCCLIBDIR}/\" \ + -Dos_${TARGOS} -DTARGMACH=${TARGMACH} -Dmach_${TARGMACH} \ + -I${top_builddir} -I${top_srcdir}/os/${TARGOS} -I${MIPDIR} -I${MDIR} +LIBS = @LIBS@ +LDFLAGS = @LDFLAGS@ +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ + +OBJS=cc.o compat.o +DEST=@BINPREFIX@pcc$(EXEEXT) + +MIPDIR=${top_srcdir}/mip +MDIR=${top_srcdir}/arch/$(TARGMACH) + +all: ${DEST} + +${DEST}: $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@ + +.c.o: + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c $< + +compat.o: $(MIPDIR)/compat.c + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/compat.c + +install: + test -z "${DESTDIR}$(bindir)" || mkdir -p "${DESTDIR}$(bindir)" + ${INSTALL_PROGRAM} ${DEST} ${DESTDIR}${bindir} + @if [ ${strip} = yes ]; then \ + strip ${DESTDIR}${bindir}/${DEST} ; \ + echo strip ${DESTDIR}${bindir}/${DEST} ; \ + fi + test -z "${DESTDIR}$(mandir)/man1" || mkdir -p "${DESTDIR}$(mandir)/man1" + ${INSTALL} $(srcdir)/cc.1 ${DESTDIR}${mandir}/man1/${DEST}.1 + test -z "${DESTDIR}$(PCCINCDIR)" || mkdir -p "${DESTDIR}$(PCCINCDIR)" + test -z "${DESTDIR}$(PCCLIBDIR)" || mkdir -p "${DESTDIR}$(PCCLIBDIR)" + +clean: + /bin/rm -f $(OBJS) ${DEST} + +distclean: clean + /bin/rm -f Makefile diff --git a/compilers/pcc/pcc-1.0.0/cc/cc/cc.1 b/compilers/pcc/pcc-1.0.0/cc/cc/cc.1 new file mode 100644 index 00000000..23bb4dc0 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cc/cc.1 @@ -0,0 +1,335 @@ +.\" $Id: cc.1,v 1.16 2010/04/05 14:24:06 reed Exp $ +.\" $NetBSD$ +.\" $OpenBSD$ +.\" +.\" Copyright (c) 2007 Jeremy C. Reed +.\" +.\" Permission to use, copy, modify, and/or distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR AND CONTRIBUTORS DISCLAIM +.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHOR AND +.\" CONTRIBUTORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +.\" THIS SOFTWARE. +.\" +.Dd September 14, 2007 +.Dt CC 1 +.Os +.Sh NAME +.Nm cc +.Nd front-end to the C compiler +.Sh SYNOPSIS +.Nm +.Op Fl cEgkLMPOStvXx +.Op Fl fPIC +.Op Fl fpic +.Op Fl m Ns Ar option +.Op Fl nostartfiles +.Op Fl nostdinc +.Op Fl nostdlib +.Op Fl pg +.Op Fl pthread +.Op Fl static +.Op Fl B Ar prefix +.Op Fl D Ar macro[=value] +.Op Fl d Ar option +.Op Fl I Ar directory +.Op Fl include Ar path +.Op Fl isystem Ar path +.Op Fl o Ar outfile +.Op Fl Wl Ar flags +.Op Ar +.Sh DESCRIPTION +The +.Nm +utility provides a front-end to the +.Dq portable C compiler . +Multiple files may be given on the command line. +Unrecognized options are all sent directly to +.Xr ld 1 . +.Pp +.\" Brief description of its syntax: +Filenames that end with +.Sy \&.c +are passed via +.Xr cpp 1 +\(-> +.Xr ccom 1 +\(-> +.Xr as 1 +\(-> +.Xr ld 1 . +.Pp +Filenames that end with +.Sy \&.i +are passed via +.Xr ccom 1 +\(-> +.Xr as 1 +\(-> +.Xr ld 1 . +.Pp +Filenames that end with +.Sy \&.s +are passed via +.Xr as 1 +\(-> +.Xr ld 1 . +.Pp +Filenames that end with +.Sy \&.S +are passed via +.Xr cpp 1 +\(-> +.Xr as 1 +\(-> +.Xr ld 1 . +.Pp +Filenames that end with +.Sy \&.o +are passed directly to +.Xr ld 1 . +.Pp +.\" +The options are as follows: +.Bl -tag -width Ds +.It Fl B Ar prefix +Define alternate prefix path for +.Xr cpp 1 , +.Xr ccom 1 , +.Xr as 1 , +or +.Xr ld 1 +executables. +.\" TODO: provide an example of -B +.It Fl C +Passed to the +.Xr cpp 1 +preprocessor to not discard comments. +.It Fl c +Only compile or assemble and then stop. +Do not link. +The resulting object output is saved +as a filename with a +.Dq \&.o +suffix unless +.Fl o +option is used. +Note: cannot be combined with +.Fl o +if multiple files are given. +.It Fl D Ar macro[=value] +Passed to the +.Xr cpp 1 +preprocessor to define +.Ar macro . +.It Fl d Ar option +Passed to the +.Xr as 1 +assembler. +.\" TODO: what is as -dfoo for? +.It Fl E +Stop after preprocessing with +.Xr cpp 1 . +Do not compile, assemble, or link. +Output is sent to standard output unless the +.Fl o +option is used. +.It Fl fPIC +Generate PIC code. +.\" TODO: document about avoiding machine-specific maximum size? +.It Fl fpic +Tells C compiler to generate PIC code +and tells assembler that PIC code has been generated. +.\" TODO: document difference between PIC and pic +.\" other -f GCC compatibility flags are ignored for now +.It Fl g +Send +.Fl g +flag to +.Xr ccom 1 +to create debug output. +This unsets the +.Fl O +option. +.It Fl I Ar path +Passed to the +.Xr cpp 1 +preprocessor to add header search directory to override system defaults. +.It Fl include Ar file +Tells the +.Xr cpp 1 +preprocessor to include the +.Ar file +during preprocessing. +.It Fl isystem Ar path +Defines +.Ar path +as a system header directory for the +.Xr cpp 1 +preprocessor. +.It Fl k +Generate PIC code. +See +.Fl fpic +option. +.It Fl L +TODO +.It Fl M +Pass +.Fl M +flag to +.Xr cpp 1 +to generate dependencies for +.Xr make 1 . +.It Fl m Ns options +Target-dependent option. +.Bl -tag -width PowerPC +.It ARM +\-mlittle-endian \-mbig-endian \-mfpe=fpa \-mfpe=vpf \-msoft-float \-march=armv1 \-march=armv2 \-march=armv2a \-march=armv3 \-march=armv4 \-march=armv4t \-march=armv4tej \-march=armv5 \-march=armv6 \-march=armv6t2 \-march=armv6kz \-march=armv6k \-march=armv7 +.It HPPA +.It i386 +.It MIPS +\-mlittle-endian \-mbig-endian \-mhard-float \-msoft-float +.It PDP-10 +.It PowerPC +.It Sparc64 +.It VAX +.El +.It Fl nostartfiles +Do not link with the system startup files (crt0.c, etc.) +.It Fl nostdinc +Do not use the system include paths (/usr/include, etc.) +.It Fl nostdlib +Do not link with the system C library (libc). +.\" implies -nostartfiles ?? +.It Fl O +Enable optimizations. +Currently passes +.Fl xdeljumps +and +.Fl xtemps +to +.Xr ccom 1 . +Note: this is unset if the +.Fl g +option is used. +.It Fl o Ar outfile +Save result to +.Ar outfile . +.It Fl P +TODO +.\" TODO: what is this? +.\" TODO: Looks like it does cpp only, but I couldn't get it to work for me. +.It Fl pg +Enable profiling on the generated executable. +.It Fl pthread +Defines +.Sy _PTHREADS +preprocessor directive for +.Xr cpp 1 . +Uses +.Sy \-lpthread +for the +.Xr ld 1 +linker. +.It Fl S +Stop after compilation by +.Xr ccom 1 . +Do not assemble and do not link. +The resulting assembler-language output is saved +as a filename with a +.Dq \&.s +suffix unless the +.Fl o +option is used. +Note: cannot be combined with +.Fl o +if multiple files are given. +.It Fl static +Do not use dynamic linkage. +By default, it will link using the dynamic linker options +and/or shared objects for the platform. +.It Fl shared +Create a shared object of the result. Tells the linker not to +generate an executable. +.It Fl t +Passes +.Fl t +to +.Xr cpp 1 +for traditional C preprocessor syntax. +.It Fl U Ar macro +Passes to the +.Xr cpp 1 +preprocessor to remove the initial macro definition. +.It Fl v +Outputs the version of +.Nm +and shows what commands will be run with their command line arguments. +.It Fl Wl Ar flags +Options for the linker. +.\" what is ignored? llist? +.It Fl X +Don't remove temporary files on exit. +.It Fl x +May be used to give separate optimization flags to ccom, see +.Fl O +for options. +.It Fl x Ar c +Gcc compatibility option; specify that the language in use is +.Ar c . +.El +.Ss Predefined Macros +A few +macros are predefined by +.Nm +when sent to +.Xr cpp 1 . +.Bl -diag +.\" TODO: +.\" .It __ASSEMBLER__ +.\" Defined if suffix is .S -- why not with .s? what does this mean? +.It __PCC__ +Set to the major version of +.Xr pcc 1 . +These macros can be used to select code based on +.Xr pcc 1 +compatibility. +See the +.Fl v +option. +.It __PCC_MINOR__ +Set to the minor version. +.It __PCC_MINORMINOR__ +Set to the minor-minor version \(em the number after the minor version. +.It _PTHREADS +Defined when +.Fl pthread +switch is used. +.El +.Pp +Also system- and/or machine-dependent macros may also be predefined; +for example: +.Dv __NetBSD__ , +.Dv __ELF__ , +and +.Dv __i386__ . +.Sh SEE ALSO +.Xr as 1 , +.Xr ccom 1 , +.Xr cpp 1 , +.Xr ld 1 +.Sh HISTORY +The +.Nm +command comes from the original Portable C Compiler by S. C. Johnson, +written in the late 70's. +.Pp +This product includes software developed or owned by Caldera +International, Inc. diff --git a/compilers/pcc/pcc-1.0.0/cc/cc/cc.c b/compilers/pcc/pcc-1.0.0/cc/cc/cc.c new file mode 100644 index 00000000..661d8e2b --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cc/cc.c @@ -0,0 +1,1535 @@ +/* $Id: cc.c,v 1.170.2.1 2011/03/15 19:25:36 ragge Exp $ */ +/* + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code and documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditionsand the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Front-end to the C compiler. + * + * Brief description of its syntax: + * - Files that end with .c are passed via cpp->ccom->as->ld + * - Files that end with .i are passed via ccom->as->ld + * - Files that end with .s are passed as->ld + * - Files that end with .o are passed directly to ld + * - Multiple files may be given on the command line. + * - Unrecognized options are all sent directly to ld. + * -c or -S cannot be combined with -o if multiple files are given. + * + * This file should be rewritten readable. + */ +#include "config.h" + +#include +#ifdef HAVE_SYS_WAIT_H +#include +#endif + +#include +#include +#include +#ifdef HAVE_LIBGEN_H +#include +#endif +#include +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef WIN32 +#include +#include +#include +#endif + +#include "compat.h" + +#include "ccconfig.h" +#include "macdefs.h" +/* C command */ + +#define MKS(x) _MKS(x) +#define _MKS(x) #x + +/* + * Many specific definitions, should be declared elsewhere. + */ + +#ifndef STDINC +#define STDINC "/usr/include/" +#endif + +#ifndef LIBDIR +#define LIBDIR "/usr/lib/" +#endif + +#ifndef PREPROCESSOR +#define PREPROCESSOR "cpp" +#endif + +#ifndef COMPILER +#define COMPILER "ccom" +#endif + +#ifndef ASSEMBLER +#define ASSEMBLER "as" +#endif + +#ifndef LINKER +#define LINKER "ld" +#endif + +#define OS MKS(TARGOS) +#define MACH MKS(TARGMACH) +#ifndef PCCINCDIR +#define PCCINCDIR LIBDIR "pcc/" MACH "-" OS "/" PACKAGE_VERSION "/include" +#endif +#ifndef PCCLIBDIR +#define PCCLIBDIR LIBDIR "pcc/" MACH "-" OS "/" PACKAGE_VERSION "/lib" +#endif + +#define MAXFIL 10000 +#define MAXLIB 10000 +#define MAXAV 10000 +#define MAXOPT 200 +char *tmp3; +char *tmp4; +char *outfile, *ermfile; +char *Bprefix(char *); +char *copy(char *, int); +char *setsuf(char *, char); +int getsuf(char *); +int main(int, char *[]); +void error(char *, ...); +void errorx(int, char *, ...); +int callsys(char [], char *[]); +int cunlink(char *); +void dexit(int); +void idexit(int); +char *gettmp(void); +void *ccmalloc(int size); +#ifdef WIN32 +char *win32pathsubst(char *); +char *win32commandline(char *, char *[]); +#endif +char *av[MAXAV]; +char *clist[MAXFIL]; +char *olist[MAXFIL]; +char *llist[MAXLIB]; +char *aslist[MAXAV]; +char *cpplist[MAXAV]; +char alist[20]; +char *xlist[100]; +int xnum; +char *mlist[100]; +char *flist[100]; +char *wlist[100]; +char *idirafter; +int nm; +int nf; +int nw; +int sspflag; +int dflag; +int pflag; +int sflag; +int cflag; +int eflag; +int gflag; +int rflag; +int vflag; +int tflag; +int Eflag; +int Oflag; +int kflag; /* generate PIC/pic code */ +#define F_PIC 1 +#define F_pic 2 +int Mflag; /* dependencies only */ +int pgflag; +int exfail; +int Xflag; +int Wallflag; +int Wflag; +int nostartfiles, Bstatic, shared; +int nostdinc, nostdlib; +int onlyas; +int pthreads; +int xcflag; +int ascpp; + +char *passp = LIBEXECDIR PREPROCESSOR; +char *pass0 = LIBEXECDIR COMPILER; +char *as = ASSEMBLER; +char *ld = LINKER; +char *Bflag; +char *cppadd[] = CPPADD; +#ifdef DYNLINKER +char *dynlinker[] = DYNLINKER; +#endif +#ifdef CRT0FILE +char *crt0file = CRT0FILE; +#endif +#ifdef CRT0FILE_PROFILE +char *crt0file_profile = CRT0FILE_PROFILE; +#endif +#ifdef STARTFILES +char *startfiles[] = STARTFILES; +char *endfiles[] = ENDFILES; +#endif +#ifdef STARTFILES_T +char *startfiles_T[] = STARTFILES_T; +char *endfiles_T[] = ENDFILES_T; +#endif +#ifdef STARTFILES_S +char *startfiles_S[] = STARTFILES_S; +char *endfiles_S[] = ENDFILES_S; +#endif +#ifdef MULTITARGET +char *mach = DEFMACH; +struct cppmd { + char *mach; + char *cppmdadd[MAXCPPMDARGS]; +}; + +struct cppmd cppmds[] = CPPMDADDS; +#else +char *cppmdadd[] = CPPMDADD; +#endif +#ifdef LIBCLIBS +char *libclibs[] = LIBCLIBS; +#else +char *libclibs[] = { "-lc", NULL }; +#endif +#ifdef LIBCLIBS_PROFILE +char *libclibs_profile[] = LIBCLIBS_PROFILE; +#else +char *libclibs_profile[] = { "-lc_p", NULL }; +#endif +#ifndef STARTLABEL +#define STARTLABEL "__start" +#endif +char *incdir = STDINC; +char *altincdir = INCLUDEDIR "pcc/"; +char *libdir = LIBDIR; +char *pccincdir = PCCINCDIR; +char *pcclibdir = PCCLIBDIR; +#ifdef mach_amd64 +int amd64_i386; +#endif + +/* handle gcc warning emulations */ +struct Wflags { + char *name; + int flags; +#define INWALL 1 +#define NEGATIVE 2 +} Wflags[] = { + { "-Wtruncate", 0 }, + { "-Wno-truncate", NEGATIVE }, + { "-Werror", 0 }, + { "-Wshadow", 0 }, + { "-Wno-shadow", NEGATIVE }, + { "-Wpointer-sign", INWALL }, + { "-Wno-pointer-sign", NEGATIVE }, + { "-Wsign-compare", 0 }, + { "-Wno-sign-compare", NEGATIVE }, + { "-Wunknown-pragmas", INWALL }, + { "-Wno-unknown-pragmas", NEGATIVE }, + { "-Wunreachable-code", 0 }, + { "-Wno-unreachable-code", NEGATIVE }, + { 0, 0 }, +}; + +#define SZWFL (sizeof(Wflags)/sizeof(Wflags[0])) + +#ifndef USHORT +/* copied from mip/manifest.h */ +#define USHORT 5 +#define INT 6 +#define UNSIGNED 7 +#endif + +/* + * Wide char defines. + */ +#if WCHAR_TYPE == USHORT +#define WCT "short unsigned int" +#define WCM "65535U" +#if WCHAR_SIZE != 2 +#error WCHAR_TYPE vs. WCHAR_SIZE mismatch +#endif +#elif WCHAR_TYPE == INT +#define WCT "int" +#define WCM "2147483647" +#if WCHAR_SIZE != 4 +#error WCHAR_TYPE vs. WCHAR_SIZE mismatch +#endif +#elif WCHAR_TYPE == UNSIGNED +#define WCT "unsigned int" +#define WCM "4294967295U" +#if WCHAR_SIZE != 4 +#error WCHAR_TYPE vs. WCHAR_SIZE mismatch +#endif +#else +#error WCHAR_TYPE not defined or invalid +#endif + +#ifdef GCC_COMPAT +#ifndef REGISTER_PREFIX +#define REGISTER_PREFIX "" +#endif +#ifndef USER_LABEL_PREFIX +#define USER_LABEL_PREFIX "" +#endif +#endif + +#ifndef PCC_PTRDIFF_TYPE +#define PCC_PTRDIFF_TYPE "long int" +#endif + +int +main(int argc, char *argv[]) +{ + struct Wflags *Wf; + char *t, *u; + char *assource; + char **pv, *ptemp[MAXOPT], **pvt; + int nc, nl, nas, ncpp, i, j, c, nxo, na; +#ifdef MULTITARGET + int k; +#endif + +#ifdef WIN32 + /* have to prefix path early. -B may override */ + incdir = win32pathsubst(incdir); + altincdir = win32pathsubst(altincdir); + libdir = win32pathsubst(libdir); + pccincdir = win32pathsubst(pccincdir); + pcclibdir = win32pathsubst(pcclibdir); + passp = win32pathsubst(passp); + pass0 = win32pathsubst(pass0); +#endif + + i = nc = nl = nas = ncpp = nxo = 0; + pv = ptemp; + while(++i < argc) { + if (argv[i][0] == '-') { + switch (argv[i][1]) { + default: + goto passa; +#ifdef notyet + /* must add library options first (-L/-l/...) */ + error("unrecognized option `-%c'", argv[i][1]); + break; +#endif + + case '-': /* double -'s */ + if (strcmp(argv[i], "--version") == 0) { + printf("%s\n", VERSSTR); + return 0; + } else if (strcmp(argv[i], "--param") == 0) { + /* NOTHING YET */; + i++; /* ignore arg */ + } else + goto passa; + break; + + case 'B': /* other search paths for binaries */ + Bflag = &argv[i][2]; + break; + +#ifdef MULTITARGET + case 'b': + t = &argv[i][2]; + if (*t == '\0' && i + 1 < argc) { + t = argv[i+1]; + i++; + } + if (strncmp(t, "?", 1) == 0) { + /* show machine targets */ + printf("Available machine targets:"); + for (j=0; cppmds[j].mach; j++) + printf(" %s",cppmds[j].mach); + printf("\n"); + exit(0); + } + for (j=0; cppmds[j].mach; j++) + if (strcmp(t, cppmds[j].mach) == 0) { + mach = cppmds[j].mach; + break; + } + if (cppmds[j].mach == NULL) + errorx(1, "unknown target arch %s", t); + break; +#endif + + case 'X': + Xflag++; + break; + case 'W': /* Ignore (most of) W-flags */ + if (strncmp(argv[i], "-Wl,", 4) == 0) { + /* options to the linker */ + t = &argv[i][4]; + while ((u = strchr(t, ','))) { + *u++ = 0; + llist[nl++] = t; + t = u; + } + llist[nl++] = t; + } else if (strncmp(argv[i], "-Wa,", 4) == 0) { + /* options to the assembler */ + t = &argv[i][4]; + while ((u = strchr(t, ','))) { + *u++ = 0; + aslist[nas++] = t; + t = u; + } + aslist[nas++] = t; + } else if (strncmp(argv[i], "-Wc,", 4) == 0) { + /* options to ccom */ + t = &argv[i][4]; + while ((u = strchr(t, ','))) { + *u++ = 0; + wlist[nw++] = t; + t = u; + } + wlist[nw++] = t; + } else if (strncmp(argv[i], "-Wp,", 4) == 0) { + /* preprocessor */ + t = &argv[i][4]; + while ((u = strchr(t, ','))) { + *u++ = 0; + cpplist[ncpp++] = t; + t = u; + } + cpplist[ncpp++] = t; + } else if (strcmp(argv[i], "-Wall") == 0) { + Wallflag = 1; + } else if (strcmp(argv[i], "-WW") == 0) { + Wflag = 1; + } else { + /* check and set if available */ + for (Wf = Wflags; Wf->name; Wf++) { + if (strcmp(argv[i], Wf->name)) + continue; + wlist[nw++] = Wf->name; + } + } + break; + + case 'f': /* GCC compatibility flags */ + if (strcmp(argv[i], "-fPIC") == 0) + kflag = F_PIC; + else if (strcmp(argv[i], "-fpic") == 0) + kflag = F_pic; + else if (strcmp(argv[i], + "-fsigned-char") == 0) + flist[nf++] = argv[i]; + else if (strcmp(argv[i], + "-fno-signed-char") == 0) + flist[nf++] = argv[i]; + else if (strcmp(argv[i], + "-funsigned-char") == 0) + flist[nf++] = argv[i]; + else if (strcmp(argv[i], + "-fno-unsigned-char") == 0) + flist[nf++] = argv[i]; + else if (strcmp(argv[i], + "-fstack-protector") == 0) { + flist[nf++] = argv[i]; + sspflag++; + } else if (strcmp(argv[i], + "-fstack-protector-all") == 0) { + flist[nf++] = argv[i]; + sspflag++; + } else if (strcmp(argv[i], + "-fno-stack-protector") == 0) { + flist[nf++] = argv[i]; + sspflag = 0; + } else if (strcmp(argv[i], + "-fno-stack-protector-all") == 0) { + flist[nf++] = argv[i]; + sspflag = 0; + } + /* silently ignore the rest */ + break; + + case 'g': /* create debug output */ + gflag++; + break; + + case 'i': + if (strcmp(argv[i], "-isystem") == 0) { + *pv++ = "-S"; + *pv++ = argv[++i]; + } else if (strcmp(argv[i], "-include") == 0) { + *pv++ = "-i"; + *pv++ = argv[++i]; + } else if (strcmp(argv[i], "-idirafter") == 0) { + idirafter = argv[++i]; + } else + goto passa; + break; + + case 'k': /* generate PIC code */ + kflag = F_pic; + break; + + case 'm': /* target-dependent options */ +#ifdef mach_amd64 + /* need to call i386 ccom for this */ + if (strcmp(argv[i], "-m32") == 0) { + pass0 = LIBEXECDIR "/ccom_i386"; + amd64_i386 = 1; + break; + } +#endif + mlist[nm++] = argv[i]; + if (argv[i][2] == 0) { + /* separate second arg */ + /* give also to linker */ + llist[nl++] = argv[i++]; + mlist[nm++] = argv[i]; + llist[nl++] = argv[i]; + } + break; + + case 'n': /* handle -n flags */ + if (strcmp(argv[i], "-nostdinc") == 0) + nostdinc++; + else if (strcmp(argv[i], "-nostdlib") == 0) { + nostdlib++; + nostartfiles++; + } else if (strcmp(argv[i], "-nostartfiles") == 0) + nostartfiles = 1; + else + goto passa; + break; + + case 'p': + if (strcmp(argv[i], "-pg") == 0 || + strcmp(argv[i], "-p") == 0) + pgflag++; + else if (strcmp(argv[i], "-pthread") == 0) + pthreads++; + else if (strcmp(argv[i], "-pipe") == 0) + /* NOTHING YET */; + else if (strcmp(argv[i], "-pedantic") == 0) + /* NOTHING YET */; + else if (strcmp(argv[i], + "-print-prog-name=ld") == 0) { + printf("%s\n", LINKER); + return 0; + } else + errorx(1, "unknown option %s", argv[i]); + break; + + case 'r': + rflag = 1; + break; + + case 'x': + t = &argv[i][2]; + if (*t == 0) + t = argv[++i]; + if (strcmp(t, "c") == 0) + xcflag = 1; /* default */ + else if (strcmp(t, "assembler-with-cpp") == 0) + ascpp = 1; +#ifdef notyet + else if (strcmp(t, "c++") == 0) + cxxflag++; +#endif + else + xlist[xnum++] = argv[i]; + break; + case 't': + tflag++; + break; + case 'S': + sflag++; + cflag++; + break; + case 'o': + if (outfile) + errorx(8, "too many -o"); + outfile = argv[++i]; + break; + case 'O': + if (argv[i][2] == '0') + Oflag = 0; + else + Oflag++; + break; + case 'E': + Eflag++; + break; + case 'P': + pflag++; + *pv++ = argv[i]; + case 'c': + cflag++; + break; + +#if 0 + case '2': + if(argv[i][2] == '\0') + pref = "/lib/crt2.o"; + else { + pref = "/lib/crt20.o"; + } + break; +#endif + case 'C': + cpplist[ncpp++] = argv[i]; + break; + case 'D': + case 'I': + case 'U': + *pv++ = argv[i]; + if (argv[i][2] == 0) + *pv++ = argv[++i]; + if (pv >= ptemp+MAXOPT) { + error("Too many DIU options"); + --pv; + } + break; + + case 'M': + Mflag++; + break; + + case 'd': +#ifdef os_darwin + if (strcmp(argv[i], "-dynamiclib") == 0) { + shared = 1; + } else +#endif + if (strcmp(argv[i], "-d") == 0) { + dflag++; + strlcpy(alist, argv[i], sizeof (alist)); + } + break; + case 'v': + printf("%s\n", VERSSTR); + vflag++; + break; + + case 's': +#ifndef os_darwin + if (strcmp(argv[i], "-shared") == 0) { + shared = 1; +#ifndef os_win32 + nostdlib = 1; +#endif + } else +#endif + if (strcmp(argv[i], "-static") == 0) { + Bstatic = 1; + } else if (strncmp(argv[i], "-std", 4) == 0) { + /* ignore gcc -std= */; + } else + goto passa; + break; + } + } else { + passa: + t = argv[i]; + if (*argv[i] == '-' && argv[i][1] == 'L') + ; + else if((c=getsuf(t))=='c' || c=='S' || c=='i' || + c=='s'|| Eflag || xcflag) { + clist[nc++] = t; + if (nc>=MAXFIL) { + error("Too many source files"); + exit(1); + } + } + + /* Check for duplicate .o files. */ + for (j = getsuf(t) == 'o' ? 0 : nl; j < nl; j++) { + if (strcmp(llist[j], t) == 0) + break; + } + if ((c=getsuf(t))!='c' && c!='S' && + c!='s' && c!='i' && j==nl) { + llist[nl++] = t; + if (nl >= MAXLIB) { + error("Too many object/library files"); + exit(1); + } + if (getsuf(t)=='o') + nxo++; + } + } + } + /* Sanity checking */ + if (nc == 0 && nl == 0) + errorx(8, "no input files"); + if (outfile && (cflag || sflag || Eflag) && nc > 1) + errorx(8, "-o given with -c || -E || -S and more than one file"); + if (outfile && clist[0] && strcmp(outfile, clist[0]) == 0) + errorx(8, "output file will be clobbered"); + if (nc==0) + goto nocom; + if (pflag==0) { + if (!sflag) + tmp3 = gettmp(); + tmp4 = gettmp(); + } + if (Bflag) { + altincdir = Bflag; + pccincdir = Bflag; + pcclibdir = Bflag; + } + if (signal(SIGINT, SIG_IGN) != SIG_IGN) /* interrupt */ + signal(SIGINT, idexit); + if (signal(SIGTERM, SIG_IGN) != SIG_IGN) /* terminate */ + signal(SIGTERM, idexit); +#ifdef MULTITARGET + pass0 = copy(LIBEXECDIR "/ccom_", k = strlen(mach)); + strlcat(pass0, mach, sizeof(LIBEXECDIR "/ccom_") + k); +#endif + pvt = pv; + for (i=0; i1 && !Eflag) + printf("%s:\n", clist[i]); + onlyas = 0; + assource = tmp3; + if (getsuf(clist[i])=='S') + ascpp = 1; + if (getsuf(clist[i])=='i') { + if(Eflag) + continue; + goto com; + } else if (ascpp) { + onlyas = 1; + } else if (getsuf(clist[i])=='s') { + assource = clist[i]; + goto assemble; + } + if (pflag) + tmp4 = setsuf(clist[i], 'i'); + na = 0; + av[na++] = "cpp"; + if (vflag) + av[na++] = "-v"; + av[na++] = "-D__PCC__=" MKS(PCC_MAJOR); + av[na++] = "-D__PCC_MINOR__=" MKS(PCC_MINOR); + av[na++] = "-D__PCC_MINORMINOR__=" MKS(PCC_MINORMINOR); +#ifndef os_win32 +#ifdef GCC_COMPAT + av[na++] = "-D__GNUC__=4"; + av[na++] = "-D__GNUC_MINOR__=3"; + av[na++] = "-D__GNUC_PATCHLEVEL__=1"; + av[na++] = "-D__GNUC_STDC_INLINE__=1"; +#endif +#endif + av[na++] = "-D__VERSION__=" MKS(VERSSTR); + av[na++] = "-D__SCHAR_MAX__=" MKS(MAX_CHAR); + av[na++] = "-D__SHRT_MAX__=" MKS(MAX_SHORT); + av[na++] = "-D__INT_MAX__=" MKS(MAX_INT); + av[na++] = "-D__LONG_MAX__=" MKS(MAX_LONG); + av[na++] = "-D__LONG_LONG_MAX__=" MKS(MAX_LONGLONG); +#ifdef CHAR_UNSIGNED + av[na++] = "-D__CHAR_UNSIGNED__"; +#endif + if (ascpp) + av[na++] = "-D__ASSEMBLER__"; + if (sspflag) + av[na++] = "-D__SSP__=1"; + if (pthreads) + av[na++] = "-D_PTHREADS"; + if (Mflag) + av[na++] = "-M"; + if (Oflag) + av[na++] = "-D__OPTIMIZE__"; +#ifdef GCC_COMPAT + av[na++] = "-D__REGISTER_PREFIX__=" REGISTER_PREFIX; + av[na++] = "-D__USER_LABEL_PREFIX__=" USER_LABEL_PREFIX; + if (Oflag) + av[na++] = "-D__OPTIMIZE__"; +#endif + if (dflag) + av[na++] = alist; + for (j = 0; cppadd[j]; j++) + av[na++] = cppadd[j]; + for (j = 0; j < ncpp; j++) + av[na++] = cpplist[j]; + av[na++] = "-D__STDC_ISO_10646__=200009L"; + av[na++] = "-D__WCHAR_TYPE__=" WCT; + av[na++] = "-D__SIZEOF_WCHAR_T__=" MKS(WCHAR_SIZE); + av[na++] = "-D__WCHAR_MAX__=" WCM; + av[na++] = "-D__WINT_TYPE__=unsigned int"; + av[na++] = "-D__SIZE_TYPE__=unsigned long"; + av[na++] = "-D__PTRDIFF_TYPE__=" PCC_PTRDIFF_TYPE; + av[na++] = "-D__SIZEOF_WINT_T__=4"; +#ifdef MULTITARGET + for (k = 0; cppmds[k].mach; k++) { + if (strcmp(cppmds[k].mach, mach) != 0) + continue; + for (j = 0; cppmds[k].cppmdadd[j]; j++) + av[na++] = cppmds[k].cppmdadd[j]; + break; + } +#else + for (j = 0; cppmdadd[j]; j++) + av[na++] = cppmdadd[j]; +#endif + if (tflag) + av[na++] = "-t"; + for(pv=ptemp; pv name; Wf++) { + if (Wf->flags != INWALL) + continue; + av[na++] = Wf->name; + } + } + if (Wflag) { + /* set all positive flags */ + for (Wf = Wflags; Wf->name; Wf++) { + if (Wf->flags == NEGATIVE) + continue; + av[na++] = Wf->name; + } + } + for (j = 0; j < nw; j++) + av[na++] = wlist[j]; + for (j = 0; j < nf; j++) + av[na++] = flist[j]; +#if !defined(os_sunos) && !defined(mach_i386) + if (vflag) + av[na++] = "-v"; +#endif + if (pgflag) + av[na++] = "-p"; + if (gflag) + av[na++] = "-g"; +#ifdef os_darwin + /* darwin always wants PIC compilation */ + if (!Bstatic) + av[na++] = "-k"; +#elif defined(os_sunos) && defined(mach_i386) + if (kflag) { + av[na++] = "-K"; + av[na++] = "pic"; + } +#else + if (kflag) + av[na++] = "-k"; +#endif + if (Oflag) { + av[na++] = "-xtemps"; + av[na++] = "-xdeljumps"; + av[na++] = "-xinline"; + } + for (j = 0; j < xnum; j++) + av[na++] = xlist[j]; + for (j = 0; j < nm; j++) + av[na++] = mlist[j]; + if (getsuf(clist[i])=='i') + av[na++] = clist[i]; + else + av[na++] = tmp4; /* created by cpp */ + if (pflag || exfail) + { + cflag++; + continue; + } + if(sflag) { + if (outfile) + tmp3 = outfile; + else + tmp3 = setsuf(clist[i], 's'); + } + ermfile = av[na++] = tmp3; +#if 0 + if (proflag) { + av[3] = "-XP"; + av[4] = 0; + } else + av[3] = 0; +#endif + av[na++] = NULL; + if (callsys(pass0, av)) { + cflag++; + eflag++; + continue; + } + if (sflag) + continue; + + /* + * Assembler + */ + assemble: + na = 0; + av[na++] = as; + for (j = 0; j < nas; j++) + av[na++] = aslist[j]; +#if defined(os_win32) && defined(USE_YASM) + av[na++] = "-p"; + av[na++] = "gnu"; + av[na++] = "-f"; + av[na++] = "win32"; +#endif +#if defined(os_sunos) && defined(mach_sparc64) + av[na++] = "-m64"; +#endif +#if defined(os_darwin) + if (Bstatic) + av[na++] = "-static"; +#endif + if (vflag) + av[na++] = "-v"; + if (kflag) + av[na++] = "-k"; +#ifdef mach_amd64 + if (amd64_i386) + av[na++] = "--32"; +#endif + av[na++] = "-o"; + if (outfile && cflag) + ermfile = av[na++] = outfile; + else if (cflag) + ermfile = av[na++] = olist[i] = setsuf(clist[i], 'o'); + else + ermfile = av[na++] = olist[i] = gettmp(); + av[na++] = assource; + if (dflag) + av[na++] = alist; + av[na++] = 0; + if (callsys(as, av)) { + cflag++; + eflag++; + cunlink(tmp4); + continue; + } + cunlink(tmp4); + } + + if (Eflag || Mflag) + dexit(eflag); + + /* + * Linker + */ +nocom: + if (cflag==0 && nc+nl != 0) { + j = 0; + av[j++] = ld; +#ifndef MSLINKER + if (vflag) + av[j++] = "-v"; +#endif +#if !defined(os_sunos) && !defined(os_win32) && !defined(os_darwin) + av[j++] = "-X"; +#endif + if (shared) { +#ifdef os_darwin + av[j++] = "-dylib"; +#else + av[j++] = "-shared"; +#endif +#ifdef os_win32 + av[j++] = "-Bdynamic"; +#endif +#ifndef os_sunos + } else { +#ifndef os_win32 +#ifndef os_darwin + av[j++] = "-d"; +#endif + if (rflag) { + av[j++] = "-r"; + } else { + av[j++] = "-e"; + av[j++] = STARTLABEL; + } +#endif +#endif + if (Bstatic == 0) { /* Dynamic linkage */ +#ifdef DYNLINKER + for (i = 0; dynlinker[i]; i++) + av[j++] = dynlinker[i]; +#endif + } else { +#ifdef os_darwin + av[j++] = "-static"; +#else + av[j++] = "-Bstatic"; +#endif + } + } + if (outfile) { +#ifdef MSLINKER +#define OUTSTR "/OUT:" + char *s = copy(OUTSTR, i = strlen(outfile)); + strlcat(s, outfile, sizeof(OUTSTR) + i); + av[j++] = s; +#else + av[j++] = "-o"; + av[j++] = outfile; +#endif + } +#ifdef STARTFILES_S + if (shared) { + if (!nostartfiles) { + for (i = 0; startfiles_S[i]; i++) + av[j++] = Bprefix(startfiles_S[i]); + } + } else +#endif + { + if (!nostartfiles) { +#ifdef CRT0FILE_PROFILE + if (pgflag) { + av[j++] = Bprefix(crt0file_profile); + } else +#endif + { +#ifdef CRT0FILE + av[j++] = Bprefix(crt0file); +#endif + } +#ifdef STARTFILES_T + if (Bstatic) { + for (i = 0; startfiles_T[i]; i++) + av[j++] = Bprefix(startfiles_T[i]); + } else +#endif + { +#ifdef STARTFILES + for (i = 0; startfiles[i]; i++) + av[j++] = Bprefix(startfiles[i]); +#endif + } + } + } + i = 0; + while (i= MAXAV) + error("Too many ld options"); + } + i = 0; + while(i= MAXAV) + error("Too many ld options"); + } +#if !defined(os_darwin) && !defined(os_sunos) + /* darwin assembler doesn't want -g */ + if (gflag) + av[j++] = "-g"; +#endif +#if 0 + if (gflag) + av[j++] = "-lg"; +#endif + if (pthreads) + av[j++] = "-lpthread"; + if (!nostdlib) { +#ifdef MSLINKER +#define LFLAG "/LIBPATH:" +#else +#define LFLAG "-L" +#endif + char *s = copy(LFLAG, i = strlen(pcclibdir)); + strlcat(s, pcclibdir, sizeof(LFLAG) + i); + av[j++] = s; +#ifdef os_win32 + s = copy(LFLAG, i = strlen(libdir)); + strlcat(s, libdir, sizeof(LFLAG) + i); + av[j++] = s; +#endif + if (pgflag) { + for (i = 0; libclibs_profile[i]; i++) + av[j++] = Bprefix(libclibs_profile[i]); + } else { + for (i = 0; libclibs[i]; i++) + av[j++] = Bprefix(libclibs[i]); + } + } + if (!nostartfiles) { +#ifdef STARTFILES_S + if (shared) { + for (i = 0; endfiles_S[i]; i++) + av[j++] = Bprefix(endfiles_S[i]); + } else +#endif + { +#ifdef STARTFILES_T + if (Bstatic) { + for (i = 0; endfiles_T[i]; i++) + av[j++] = Bprefix(endfiles_T[i]); + } else +#endif + { +#ifdef STARTFILES + for (i = 0; endfiles[i]; i++) + av[j++] = Bprefix(endfiles[i]); +#endif + } + } + } + av[j++] = 0; + eflag |= callsys(ld, av); + if (nc==1 && nxo==1 && eflag==0) + cunlink(olist[0]); + else if (nc > 0 && eflag == 0) { + /* remove .o files XXX ugly */ + for (i = 0; i < nc; i++) + cunlink(olist[i]); + } + } + dexit(eflag); + return 0; +} + +/* + * exit and cleanup after interrupt. + */ +void +idexit(int arg) +{ + dexit(100); +} + +/* + * exit and cleanup. + */ +void +dexit(int eval) +{ + if (!pflag && !Xflag) { + if (sflag==0) + cunlink(tmp3); + cunlink(tmp4); + } + if (exfail || eflag) + cunlink(ermfile); + if (eval == 100) + _exit(eval); + exit(eval); +} + +static void +ccerror(char *s, va_list ap) +{ + vfprintf(Eflag ? stderr : stdout, s, ap); + putc('\n', Eflag? stderr : stdout); + exfail++; + cflag++; + eflag++; +} + +/* + * complain a bit. + */ +void +error(char *s, ...) +{ + va_list ap; + + va_start(ap, s); + ccerror(s, ap); + va_end(ap); +} + +/* + * complain a bit and then exit. + */ +void +errorx(int eval, char *s, ...) +{ + va_list ap; + + va_start(ap, s); + ccerror(s, ap); + va_end(ap); + dexit(eval); +} + +char * +Bprefix(char *s) +{ + char *suffix; + char *str; + int i; + +#ifdef WIN32 + + /* put here to save sprinkling it ~everywhere */ + s = win32pathsubst(s); + + if (Bflag == NULL) + return s; + suffix = strrchr(s, '/'); + if (suffix == NULL) + suffix = strrchr(s, '\\'); + +#else + + if (Bflag == NULL || s[0] != '/') + return s; + suffix = strrchr(s, '/'); + +#endif + + if (suffix == NULL) + suffix = s; + + str = copy(Bflag, i = strlen(suffix)); + strlcat(str, suffix, strlen(Bflag) + i + 1); + return str; +} + +int +getsuf(char *s) +{ + register char *p; + + if ((p = strrchr(s, '.')) && p[1] != '\0' && p[2] == '\0') + return p[1]; + return(0); +} + +/* + * Get basename of string s and change its suffix to ch. + */ +char * +setsuf(char *s, char ch) +{ + char *p; + + s = copy(basename(s), 2); + if ((p = strrchr(s, '.')) == NULL) { + p = s + strlen(s); + p[0] = '.'; + } + p[1] = ch; + p[2] = '\0'; + return(s); +} + +#ifdef WIN32 +#define MAX_CMDLINE_LENGTH 32768 +int +callsys(char *f, char *v[]) +{ + char *cmd; + STARTUPINFO si; + PROCESS_INFORMATION pi; + DWORD exitCode; + BOOL ok; + + cmd = win32commandline(f, v); + if (vflag) + printf("%s\n", cmd); + + ZeroMemory(&si, sizeof(STARTUPINFO)); + si.cb = sizeof(STARTUPINFO); + ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); + + ok = CreateProcess(NULL, // the executable program + cmd, // the command line arguments + NULL, // ignored + NULL, // ignored + TRUE, // inherit handles + HIGH_PRIORITY_CLASS, + NULL, // ignored + NULL, // ignored + &si, + &pi); + + if (!ok) { + fprintf(stderr, "Can't find %s\n", f); + return 100; + } + + WaitForSingleObject(pi.hProcess, INFINITE); + GetExitCodeProcess(pi.hProcess, &exitCode); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + + return (exitCode != 0); +} + +#else + +int +callsys(char *f, char *v[]) +{ + int t, status = 0; + pid_t p; + char *s; + char * volatile a = NULL; + volatile size_t len; + + if (vflag) { + fprintf(stderr, "%s ", f); + for (t = 1; v[t]; t++) + fprintf(stderr, "%s ", v[t]); + fprintf(stderr, "\n"); + } + + if (Bflag) { + len = strlen(Bflag) + 8; + a = malloc(len); + } +#ifdef HAVE_VFORK + if ((p = vfork()) == 0) { +#else + if ((p = fork()) == 0) { +#endif + if (Bflag) { + if (a == NULL) { + error("callsys: malloc failed"); + exit(1); + } + if ((s = strrchr(f, '/'))) { + strlcpy(a, Bflag, len); + strlcat(a, s, len); + execv(a, v); + } + } + execvp(f, v); + if ((s = strrchr(f, '/'))) + execvp(s+1, v); + fprintf(stderr, "Can't find %s\n", f); + _exit(100); + } + if (p == -1) { + fprintf(stderr, "fork() failed, try again\n"); + return(100); + } + if (Bflag) { + free(a); + } + while (waitpid(p, &status, 0) == -1 && errno == EINTR) + ; + if (WIFEXITED(status)) + return (WEXITSTATUS(status)); + if (WIFSIGNALED(status)) + dexit(eflag ? eflag : 1); + errorx(8, "Fatal error in %s", f); + + return 0; +} +#endif + +/* + * Make a copy of string as, mallocing extra bytes in the string. + */ +char * +copy(char *s, int extra) +{ + int len = strlen(s)+1; + char *rv; + + rv = ccmalloc(len+extra); + strlcpy(rv, s, len); + return rv; +} + +int +cunlink(char *f) +{ + if (f==0 || Xflag) + return(0); + return (unlink(f)); +} + +#ifdef WIN32 +char * +gettmp(void) +{ +#define BUFFSIZE 1000 + DWORD pathSize; + char pathBuffer[BUFFSIZE]; + char tempFilename[MAX_PATH]; + UINT uniqueNum; + + pathSize = GetTempPath(BUFFSIZE, pathBuffer); + if (pathSize < BUFFSIZE) + pathBuffer[pathSize] = 0; + else + pathBuffer[0] = 0; + uniqueNum = GetTempFileName(pathBuffer, "ctm", 0, tempFilename); + if (uniqueNum == 0) { + fprintf(stderr, "%s:\n", pathBuffer); + exit(8); + } + return copy(tempFilename, 0); +} + +#else + +char * +gettmp(void) +{ + char *sfn = copy("/tmp/ctm.XXXXXX", 0); + int fd = -1; + + if ((fd = mkstemp(sfn)) == -1) { + fprintf(stderr, "%s: %s\n", sfn, strerror(errno)); + exit(8); + } + close(fd); + return sfn; +} +#endif + +void * +ccmalloc(int size) +{ + void *rv; + + if ((rv = malloc(size)) == NULL) + error("malloc failed"); + return rv; +} + +#ifdef WIN32 + +char * +win32pathsubst(char *s) +{ + char env[1024]; + char *rv; + int len; + + len = ExpandEnvironmentStrings(s, env, sizeof(env)); + if (len <= 0) + return s; + + while (env[len-1] == '/' || env[len-1] == '\\' || env[len-1] == '\0') + env[--len] = 0; + + rv = ccmalloc(len+1); + strlcpy(rv, env, len+1); + + return rv; +} + +char * +win32commandline(char *f, char *args[]) +{ + char *cmd; + char *p; + int len; + int i, j, k; + + len = strlen(f) + 3; + + for (i = 1; args[i] != NULL; i++) { + for (j = 0; args[i][j] != '\0'; j++) { + len++; + if (args[i][j] == '\"') { + for (k = j-1; k >= 0 && args[i][k] == '\\'; k--) + len++; + } + } + for (k = j-1; k >= 0 && args[i][k] == '\\'; k--) + len++; + len += j + 3; + } + + p = cmd = ccmalloc(len); + *p++ = '\"'; + p += strlcpy(p, f, len-1); + *p++ = '\"'; + *p++ = ' '; + + for (i = 1; args[i] != NULL; i++) { + *p++ = '\"'; + for (j = 0; args[i][j] != '\0'; j++) { + if (args[i][j] == '\"') { + for (k = j-1; k >= 0 && args[i][k] == '\\'; k--) + *p++ = '\\'; + *p++ = '\\'; + } + *p++ = args[i][j]; + } + for (k = j-1; k >= 0 && args[i][k] == '\\'; k--) + *p++ = '\\'; + *p++ = '\"'; + *p++ = ' '; + } + p[-1] = '\0'; + + return cmd; +} + +#endif diff --git a/compilers/pcc/pcc-1.0.0/cc/ccom/CVS/Entries b/compilers/pcc/pcc-1.0.0/cc/ccom/CVS/Entries new file mode 100644 index 00000000..c6d5af63 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/ccom/CVS/Entries @@ -0,0 +1,17 @@ +/Makefile.in/1.32/Sun Apr 11 15:01:04 2010//Tr-1-0-0-RELEASE +/builtins.c/1.18.2.2/Tue Mar 29 15:56:24 2011//Tr-1-0-0-RELEASE +/ccom.1/1.9/Mon Apr 5 13:13:57 2010//Tr-1-0-0-RELEASE +/cgram.y/1.319/Thu Jan 27 18:00:32 2011//Tr-1-0-0-RELEASE +/gcc_compat.c/1.77/Tue Feb 1 14:20:02 2011//Tr-1-0-0-RELEASE +/init.c/1.62/Sat Feb 19 17:23:39 2011//Tr-1-0-0-RELEASE +/inline.c/1.37.2.2/Sat Feb 26 11:31:45 2011//Tr-1-0-0-RELEASE +/main.c/1.106/Sat Jan 22 22:08:23 2011//Tr-1-0-0-RELEASE +/optim.c/1.36.2.1/Tue Mar 1 17:40:21 2011//Tr-1-0-0-RELEASE +/pass1.h/1.215/Thu Feb 17 13:44:13 2011//Tr-1-0-0-RELEASE +/pftn.c/1.311/Sun Feb 20 10:19:07 2011//Tr-1-0-0-RELEASE +/scan.l/1.102/Wed Feb 16 18:50:42 2011//Tr-1-0-0-RELEASE +/softfloat.c/1.4/Wed Jul 29 12:32:34 2009//Tr-1-0-0-RELEASE +/stabs.c/1.31/Wed Aug 11 14:08:44 2010//Tr-1-0-0-RELEASE +/symtabs.c/1.19/Sat Jan 22 22:08:23 2011//Tr-1-0-0-RELEASE +/trees.c/1.272.2.1/Tue Mar 1 17:39:28 2011//Tr-1-0-0-RELEASE +D diff --git a/compilers/pcc/pcc-1.0.0/cc/ccom/CVS/Repository b/compilers/pcc/pcc-1.0.0/cc/ccom/CVS/Repository new file mode 100644 index 00000000..6713449a --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/ccom/CVS/Repository @@ -0,0 +1 @@ +pcc/cc/ccom diff --git a/compilers/pcc/pcc-1.0.0/cc/ccom/CVS/Root b/compilers/pcc/pcc-1.0.0/cc/ccom/CVS/Root new file mode 100644 index 00000000..71e2ccb9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/ccom/CVS/Root @@ -0,0 +1 @@ +/cvsroot diff --git a/compilers/pcc/pcc-1.0.0/cc/ccom/CVS/Tag b/compilers/pcc/pcc-1.0.0/cc/ccom/CVS/Tag new file mode 100644 index 00000000..060fac05 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/ccom/CVS/Tag @@ -0,0 +1 @@ +Nr-1-0-0-RELEASE diff --git a/compilers/pcc/pcc-1.0.0/cc/ccom/Makefile.in b/compilers/pcc/pcc-1.0.0/cc/ccom/Makefile.in new file mode 100644 index 00000000..40314895 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/ccom/Makefile.in @@ -0,0 +1,139 @@ +# $Id: Makefile.in,v 1.32 2010/04/11 15:01:04 ragge Exp $ +# +# Makefile.in for ccom +# +VPATH=@srcdir@ +srcdir=@srcdir@ +top_srcdir=@top_srcdir@ +builddir=@builddir@ +top_builddir=@top_builddir@ +XFL=-DPCC_DEBUG +CC = @CC@ +EXEEXT = @EXEEXT@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +_CFLAGS = @CFLAGS@ +CFLAGS = $(_CFLAGS) @ADD_CFLAGS@ +CPPFLAGS = @ADD_CPPFLAGS@ ${XFL} -Dos_${TARGOS} -Dmach_${TARGMACH} \ + -D_ISOC99_SOURCE \ + -I${srcdir} -I${builddir} -I${top_builddir} -I${MIPDIR} -I${MDIR} \ + -I${top_srcdir}/os/${TARGOS} +LIBS = @LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +YACC = @YACC@ +TARGOS = @targos@ +TARGMACH = @targmach@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +libexecdir = @libexecdir@ +datarootdir = @datarootdir@ +mandir = @mandir@ +strip = @strip@ +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ + +MDIR=$(top_srcdir)/arch/$(TARGMACH) +MIPDIR=$(top_srcdir)/mip + +OBJS1=optim.o pftn.o scan.o trees.o cgram.o inline.o symtabs.o \ + gcc_compat.o init.o local.o code.o stabs.o builtins.o + +OBJS2=match.o reader.o optim2.o regs.o local2.o order.o table.o + +OBJS=$(OBJS1) $(OBJS2) compat.o common.o main.o external.o + +DEST=@BINPREFIX@ccom$(EXEEXT) + +all: ${DEST} + +${DEST}: $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@ + +.c.o: + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< + +local.o: $(MDIR)/local.c external.h + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MDIR)/local.c + +local2.o: $(MDIR)/local2.c external.h + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MDIR)/local2.c + +code.o: $(MDIR)/code.c external.h + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MDIR)/code.c + +order.o: $(MDIR)/order.c external.h + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MDIR)/order.c + +table.o: $(MDIR)/table.c external.h + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MDIR)/table.c + +match.o: $(MIPDIR)/match.c external.h + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/match.c + +reader.o: $(MIPDIR)/reader.c external.h + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/reader.c + +optim2.o: $(MIPDIR)/optim2.c external.h + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/optim2.c + +regs.o: $(MIPDIR)/regs.c external.h + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/regs.c + +cgram.o: cgram.c external.h + $(CC) $(DEFS) $(CPPFLAGS) $(_CFLAGS) -c -o $@ cgram.c + +scan.o: scan.c external.h + $(CC) $(DEFS) $(CPPFLAGS) $(_CFLAGS) -c -o $@ scan.c + +common.o: $(MIPDIR)/common.c external.h + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/common.c + +compat.o: $(MIPDIR)/compat.c external.h + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/compat.c + +external.h external.c: ${MIPDIR}/mkext.c $(MDIR)/table.c + $(CC_FOR_BUILD) $(DEFS) $(CPPFLAGS) $(CFLAGS) -DMKEXT -o mkext \ + ${MIPDIR}/mkext.c $(MDIR)/table.c ${MIPDIR}/common.c + ./mkext + +trees.c: ../../mip/pass2.h external.h + +inline.c: external.h +init.c: external.h +pftn.c: external.h +gcc_compat.c: external.h +symtabs.c: external.h +stabs.c: external.h +main.c: external.h + +pass1.h: external.h +pass2.h: external.h + +cgram.c: cgram.y + $(YACC) $(YFLAGS) -d $< + mv y.tab.c cgram.c + mv y.tab.h cgram.h + +scan.c: scan.l cgram.c + $(LEX) $(LFLAGS) $< + mv lex.yy.c scan.c + +optim2.o reader.o optim.o : external.h + +pftn.o: cgram.c # creates cgram.h also + +install: + test -z "${DESTDIR}$(libexecdir)" || mkdir -p "${DESTDIR}$(libexecdir)" + ${INSTALL_PROGRAM} ${DEST} ${DESTDIR}${libexecdir} + @if [ ${strip} = yes ]; then \ + strip ${DESTDIR}${libexecdir}/${DEST} ; \ + echo strip ${DESTDIR}${libexecdir}/${DEST} ; \ + fi + test -z "${DESTDIR}$(mandir)/man1" || mkdir -p "${DESTDIR}$(mandir)/man1" + ${INSTALL} $(srcdir)/ccom.1 ${DESTDIR}${mandir}/man1/$(DEST).1 + +clean: + /bin/rm -f $(OBJS) $(DEST) scan.c cgram.[ch] mkext external.[ch] + +distclean: clean + /bin/rm -f Makefile diff --git a/compilers/pcc/pcc-1.0.0/cc/ccom/builtins.c b/compilers/pcc/pcc-1.0.0/cc/ccom/builtins.c new file mode 100644 index 00000000..192cfbe9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/ccom/builtins.c @@ -0,0 +1,638 @@ +/* $Id: builtins.c,v 1.18.2.2 2011/03/29 15:56:24 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +# include "pass1.h" + +#ifndef MIN +#define MIN(a,b) (((a)<(b))?(a):(b)) +#endif +#ifndef MAX +#define MAX(a,b) (((a)>(b))?(a):(b)) +#endif + +#ifndef NO_C_BUILTINS +/* + * replace an alloca function with direct allocation on stack. + * return a destination temp node. + */ +static NODE * +builtin_alloca(NODE *f, NODE *a, TWORD rt) +{ + struct symtab *sp; + NODE *t, *u; + +#ifdef notyet + if (xnobuiltins) + return NULL; +#endif + sp = f->n_sp; + + t = tempnode(0, VOID|PTR, 0, MKAP(INT) /* XXX */); + u = tempnode(regno(t), VOID|PTR, 0, MKAP(INT) /* XXX */); + spalloc(t, a, SZCHAR); + tfree(f); + return u; +} + +/* + * See if there is a goto in the tree. + * XXX this function is a hack for a flaw in handling of + * compound expressions and inline functions and should not be + * needed. + */ +static int +hasgoto(NODE *p) +{ + int o = coptype(p->n_op); + + if (o == LTYPE) + return 0; + if (p->n_op == GOTO) + return 1; + if (o == UTYPE) + return hasgoto(p->n_left); + if (hasgoto(p->n_left)) + return 1; + return hasgoto(p->n_right); +} + +/* + * Determine if a value is known to be constant at compile-time and + * hence that PCC can perform constant-folding on expressions involving + * that value. + */ +static NODE * +builtin_constant_p(NODE *f, NODE *a, TWORD rt) +{ + void putjops(NODE *p, void *arg); + int isconst; + + tfree(f); + walkf(a, putjops, 0); + for (f = a; f->n_op == COMOP; f = f->n_right) + ; + isconst = nncon(f); + tfree(a); + return bcon(isconst); +} + +/* + * Hint to the compiler whether this expression will evaluate true or false. + * Just ignored for now. + */ +static NODE * +builtin_expect(NODE *f, NODE *a, TWORD rt) +{ + + tfree(f); + if (a && a->n_op == CM) { + tfree(a->n_right); + f = a->n_left; + nfree(a); + a = f; + } + + return a; +} + +/* + * Take integer absolute value. + * Simply does: ((((x)>>(8*sizeof(x)-1))^(x))-((x)>>(8*sizeof(x)-1))) + */ +static NODE * +builtin_abs(NODE *f, NODE *a, TWORD rt) +{ + NODE *p, *q, *r, *t, *t2, *t3; + int tmp1, tmp2, shift; + + if (a->n_type != INT) + a = cast(a, INT, 0); + + tfree(f); + + if (a->n_op == ICON) { + if (a->n_lval < 0) + a->n_lval = -a->n_lval; + p = a; + } else { + t = tempnode(0, a->n_type, a->n_df, a->n_ap); + tmp1 = regno(t); + p = buildtree(ASSIGN, t, a); + + t = tempnode(tmp1, a->n_type, a->n_df, a->n_ap); + shift = (int)tsize(a->n_type, a->n_df, a->n_ap) - 1; + q = buildtree(RS, t, bcon(shift)); + + t2 = tempnode(0, a->n_type, a->n_df, a->n_ap); + tmp2 = regno(t2); + q = buildtree(ASSIGN, t2, q); + + t = tempnode(tmp1, a->n_type, a->n_df, a->n_ap); + t2 = tempnode(tmp2, a->n_type, a->n_df, a->n_ap); + t3 = tempnode(tmp2, a->n_type, a->n_df, a->n_ap); + r = buildtree(MINUS, buildtree(ER, t, t2), t3); + + p = buildtree(COMOP, p, buildtree(COMOP, q, r)); + } + + return p; +} + +/* + * Get size of object, if possible. + * Currently does nothing, + */ +static NODE * +builtin_object_size(NODE *f, NODE *a, TWORD rt) +{ + int v = icons(a->n_right); + if (v < 0 || v > 3) + uerror("arg2 must be between 0 and 3"); + + tfree(f); + f = buildtree(COMOP, a->n_left, xbcon(v < 2 ? -1 : 0, NULL, rt)); + nfree(a); + return f; +} + +#ifndef TARGET_STDARGS +static NODE * +builtin_stdarg_start(NODE *f, NODE *a, TWORD rt) +{ + NODE *p, *q; + int sz; + + /* must first deal with argument size; use int size */ + p = a->n_right; + if (p->n_type < INT) { + sz = (int)(SZINT/tsize(p->n_type, p->n_df, p->n_ap)); + } else + sz = 1; + + /* do the real job */ + p = buildtree(ADDROF, p, NIL); /* address of last arg */ +#ifdef BACKAUTO + p = optim(buildtree(PLUS, p, bcon(sz))); /* add one to it (next arg) */ +#else + p = optim(buildtree(MINUS, p, bcon(sz))); /* add one to it (next arg) */ +#endif + q = block(NAME, NIL, NIL, PTR+VOID, 0, 0); /* create cast node */ + q = buildtree(CAST, q, p); /* cast to void * (for assignment) */ + p = q->n_right; + nfree(q->n_left); + nfree(q); + p = buildtree(ASSIGN, a->n_left, p); /* assign to ap */ + tfree(f); + nfree(a); + return p; +} + +static NODE * +builtin_va_arg(NODE *f, NODE *a, TWORD rt) +{ + NODE *p, *q, *r, *rv; + int sz, nodnum; + + /* create a copy to a temp node of current ap */ + p = ccopy(a->n_left); + q = tempnode(0, p->n_type, p->n_df, p->n_ap); + nodnum = regno(q); + rv = buildtree(ASSIGN, q, p); + + r = a->n_right; + sz = (int)tsize(r->n_type, r->n_df, r->n_ap)/SZCHAR; + /* add one to ap */ +#ifdef BACKAUTO + rv = buildtree(COMOP, rv , buildtree(PLUSEQ, a->n_left, bcon(sz))); +#else +#error fix wrong eval order in builtin_va_arg + ecomp(buildtree(MINUSEQ, a->n_left, bcon(sz))); +#endif + + nfree(a->n_right); + nfree(a); + nfree(f); + r = tempnode(nodnum, INCREF(r->n_type), r->n_df, r->n_ap); + return buildtree(COMOP, rv, buildtree(UMUL, r, NIL)); + +} + +static NODE * +builtin_va_end(NODE *f, NODE *a, TWORD rt) +{ + tfree(f); + tfree(a); + return bcon(0); /* nothing */ +} + +static NODE * +builtin_va_copy(NODE *f, NODE *a, TWORD rt) +{ + tfree(f); + f = buildtree(ASSIGN, a->n_left, a->n_right); + nfree(a); + return f; +} +#endif /* TARGET_STDARGS */ + +/* + * For unimplemented "builtin" functions, try to invoke the + * non-builtin name + */ +static NODE * +binhelp(NODE *f, NODE *a, TWORD rt, char *n) +{ + f->n_sp = lookup(addname(n), SNORMAL); + if (f->n_sp->sclass == SNULL) { + f->n_sp->sclass = EXTERN; + f->n_sp->stype = INCREF(rt)+(FTN-PTR); + } + f->n_type = f->n_sp->stype; + f = clocal(f); + return buildtree(CALL, f, a); +} + +static NODE * +builtin_unimp(NODE *f, NODE *a, TWORD rt) +{ + char *n = f->n_sp->sname; + + if (strncmp("__builtin_", n, 10) == 0) + n += 10; + return binhelp(f, a, rt, n); +} + +static NODE * +builtin_unimp_f(NODE *f, NODE *a, TWORD rt) +{ + return binhelp(f, a, rt, f->n_sp->sname); +} + +#ifndef TARGET_ISMATH +/* + * Handle the builtin macros for the math functions is* + * To get something that is be somewhat generic assume that + * isnan() is a real function and that cast of a NaN type + * to double will still be a NaN. + */ +static NODE * +mtisnan(NODE *p) +{ + NODE *q = block(NAME, NIL, NIL, INT, 0, MKAP(INT)); + + return binhelp(q, cast(ccopy(p), DOUBLE, 0), INT, "isnan"); +} + +static TWORD +mtcheck(NODE *p) +{ + TWORD t1 = p->n_left->n_type, t2 = p->n_right->n_type; + + if ((t1 >= FLOAT && t1 <= LDOUBLE) || + (t2 >= FLOAT && t2 <= LDOUBLE)) + return MAX(t1, t2); + return 0; +} + +static NODE * +builtin_isunordered(NODE *f, NODE *a, TWORD rt) +{ + NODE *p; + + if (mtcheck(a) == 0) + return bcon(0); + + p = buildtree(OROR, mtisnan(a->n_left), mtisnan(a->n_right)); + tfree(f); + tfree(a); + return p; +} +static NODE * +builtin_isany(NODE *f, NODE *a, TWORD rt, int cmpt) +{ + NODE *p, *q; + TWORD t; + + if ((t = mtcheck(a)) == 0) + return bcon(0); + p = buildtree(OROR, mtisnan(a->n_left), mtisnan(a->n_right)); + p = buildtree(NOT, p, NIL); + q = buildtree(cmpt, cast(ccopy(a->n_left), t, 0), + cast(ccopy(a->n_right), t, 0)); + p = buildtree(ANDAND, p, q); + tfree(f); + tfree(a); + return p; +} +static NODE * +builtin_isgreater(NODE *f, NODE *a, TWORD rt) +{ + return builtin_isany(f, a, rt, GT); +} +static NODE * +builtin_isgreaterequal(NODE *f, NODE *a, TWORD rt) +{ + return builtin_isany(f, a, rt, GE); +} +static NODE * +builtin_isless(NODE *f, NODE *a, TWORD rt) +{ + return builtin_isany(f, a, rt, LT); +} +static NODE * +builtin_islessequal(NODE *f, NODE *a, TWORD rt) +{ + return builtin_isany(f, a, rt, LE); +} +static NODE * +builtin_islessgreater(NODE *f, NODE *a, TWORD rt) +{ + NODE *p, *q, *r; + TWORD t; + + if ((t = mtcheck(a)) == 0) + return bcon(0); + p = buildtree(OROR, mtisnan(a->n_left), mtisnan(a->n_right)); + p = buildtree(NOT, p, NIL); + q = buildtree(GT, cast(ccopy(a->n_left), t, 0), + cast(ccopy(a->n_right), t, 0)); + r = buildtree(LT, cast(ccopy(a->n_left), t, 0), + cast(ccopy(a->n_right), t, 0)); + q = buildtree(OROR, q, r); + p = buildtree(ANDAND, p, q); + tfree(f); + tfree(a); + return p; +} +#endif + +/* + * Math-specific builtins that expands to constants. + * Versins here is for IEEE FP, vax needs its own versions. + */ +#ifdef RTOLBYTES +static char vFLOAT[] = { 0, 0, 0x80, 0x7f }; +static char vDOUBLE[] = { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f }; +#ifdef LDBL_128 +static char vLDOUBLE[] = { 0,0,0,0,0,0,0, 0, 0, 0, 0, 0, 0, 0x80, 0xff, 0x7f }; +#else /* LDBL_80 */ +static char vLDOUBLE[] = { 0, 0, 0, 0, 0, 0, 0, 0x80, 0xff, 0x7f }; +#endif +static char nFLOAT[] = { 0, 0, 0xc0, 0x7f }; +static char nDOUBLE[] = { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f }; +#ifdef LDBL_128 +static char nLDOUBLE[] = { 0,0,0,0,0,0,0,0, 0, 0, 0, 0, 0, 0xc0, 0xff, 0x7f }; +#else /* LDBL_80 */ +static char nLDOUBLE[] = { 0, 0, 0, 0, 0, 0, 0, 0xc0, 0xff, 0x7f, 0, 0 }; +#endif +#else +static char vFLOAT[] = { 0x7f, 0x80, 0, 0 }; +static char vDOUBLE[] = { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 }; +#ifdef LDBL_128 +static char vLDOUBLE[] = { 0x7f, 0xff, 0x80, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0 }; +#else /* LDBL_80 */ +static char vLDOUBLE[] = { 0x7f, 0xff, 0x80, 0, 0, 0, 0, 0, 0, 0 }; +#endif +static char nFLOAT[] = { 0x7f, 0xc0, 0, 0 }; +static char nDOUBLE[] = { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 }; +#ifdef LDBL_128 +static char nLDOUBLE[] = { 0x7f, 0xff, 0xc0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0 }; +#else /* LDBL_80 */ +static char nLDOUBLE[] = { 0x7f, 0xff, 0xc0, 0, 0, 0, 0, 0, 0, 0 }; +#endif +#endif + +#define VALX(typ,TYP) { \ + typ d; \ + int x; \ + x = MIN(sizeof(n ## TYP), sizeof(d)); \ + memcpy(&d, v ## TYP, x); \ + nfree(f); \ + f = block(FCON, NIL, NIL, TYP, NULL, MKAP(TYP)); \ + f->n_dcon = d; \ + return f; \ +} + +static NODE * +builtin_huge_valf(NODE *f, NODE *a, TWORD rt) VALX(float,FLOAT) +static NODE * +builtin_huge_val(NODE *f, NODE *a, TWORD rt) VALX(double,DOUBLE) +static NODE * +builtin_huge_vall(NODE *f, NODE *a, TWORD rt) VALX(long double,LDOUBLE) + +#define builtin_inff builtin_huge_valf +#define builtin_inf builtin_huge_val +#define builtin_infl builtin_huge_vall + +#define NANX(typ,TYP) { \ + typ d; \ + int x; \ + if ((a->n_op == ICON && a->n_sp && a->n_sp->sname[0] == '\0') ||\ + (a->n_op == ADDROF && a->n_left->n_op == NAME && \ + a->n_left->n_sp && a->n_left->n_sp->sname[0] == '\0')) { \ + x = MIN(sizeof(n ## TYP), sizeof(d)); \ + memcpy(&d, n ## TYP, x); \ + tfree(a); tfree(f); \ + f = block(FCON, NIL, NIL, TYP, NULL, MKAP(TYP)); \ + f->n_dcon = d; \ + return f; \ + } \ + return buildtree(CALL, f, a); \ +} + +/* + * Return NANs, if reasonable. + */ +static NODE * +builtin_nanf(NODE *f, NODE *a, TWORD rt) NANX(float,FLOAT) +static NODE * +builtin_nan(NODE *f, NODE *a, TWORD rt) NANX(double,DOUBLE) +static NODE * +builtin_nanl(NODE *f, NODE *a, TWORD rt) NANX(long double,LDOUBLE) + +/* + * Target defines, to implement target versions of the generic builtins + */ +#ifndef TARGET_MEMCMP +#define builtin_memcmp builtin_unimp +#endif +#ifndef TARGET_MEMCPY +#define builtin_memcpy builtin_unimp +#endif +#ifndef TARGET_MEMSET +#define builtin_memset builtin_unimp +#endif + +/* Reasonable type of size_t */ +#ifndef SIZET +#if SZINT == SZSHORT +#define SIZET UNSIGNED +#elif SZLONG > SZINT +#define SIZET ULONG +#else +#define SIZET UNSIGNED +#endif +#endif + +static TWORD memcpyt[] = { VOID|PTR, VOID|PTR, SIZET, INT }; +static TWORD memsett[] = { VOID|PTR, INT, SIZET, INT }; +static TWORD allocat[] = { SIZET }; +static TWORD expectt[] = { LONG, LONG }; +static TWORD strcmpt[] = { CHAR|PTR, CHAR|PTR }; +static TWORD strcpyt[] = { CHAR|PTR, CHAR|PTR, INT }; +static TWORD strncpyt[] = { CHAR|PTR, CHAR|PTR, SIZET, INT }; +static TWORD strchrt[] = { CHAR|PTR, INT }; +static TWORD strcspnt[] = { CHAR|PTR, CHAR|PTR }; +static TWORD nant[] = { CHAR|PTR }; +static TWORD bitt[] = { UNSIGNED }; +static TWORD bitlt[] = { ULONG }; +static TWORD ffst[] = { INT }; + +static const struct bitable { + char *name; + NODE *(*fun)(NODE *f, NODE *a, TWORD); + int narg; + TWORD *tp; + TWORD rt; +} bitable[] = { + { "__builtin___memcpy_chk", builtin_unimp, 4, memcpyt, VOID|PTR }, + { "__builtin___memmove_chk", builtin_unimp, 4, memcpyt, VOID|PTR }, + { "__builtin___memset_chk", builtin_unimp, 4, memsett, VOID|PTR }, + + { "__builtin___strcat_chk", builtin_unimp, 3, strcpyt, CHAR|PTR }, + { "__builtin___strcpy_chk", builtin_unimp, 3, strcpyt, CHAR|PTR }, + { "__builtin___strncat_chk", builtin_unimp, 4, strncpyt,CHAR|PTR }, + { "__builtin___strncpy_chk", builtin_unimp, 4, strncpyt,CHAR|PTR }, + + { "__builtin___printf_chk", builtin_unimp, -1, 0, INT }, + { "__builtin___fprintf_chk", builtin_unimp, -1, 0, INT }, + { "__builtin___sprintf_chk", builtin_unimp, -1, 0, INT }, + { "__builtin___snprintf_chk", builtin_unimp, -1, 0, INT }, + { "__builtin___vprintf_chk", builtin_unimp, -1, 0, INT }, + { "__builtin___vfprintf_chk", builtin_unimp, -1, 0, INT }, + { "__builtin___vsprintf_chk", builtin_unimp, -1, 0, INT }, + { "__builtin___vsnprintf_chk", builtin_unimp, -1, 0, INT }, + + { "__builtin_alloca", builtin_alloca, 1, allocat }, + { "__builtin_abs", builtin_abs, 1 }, + { "__builtin_clz", builtin_unimp_f, 1, bitt, INT }, + { "__builtin_ctz", builtin_unimp_f, 1, bitt, INT }, + { "__builtin_clzl", builtin_unimp_f, 1, bitlt, INT }, + { "__builtin_ctzl", builtin_unimp_f, 1, bitlt, INT }, + { "__builtin_ffs", builtin_unimp, 1, ffst, INT }, + + { "__builtin_constant_p", builtin_constant_p, 1 }, + { "__builtin_expect", builtin_expect, 2, expectt }, + { "__builtin_memcmp", builtin_memcmp, 3, memcpyt, INT }, + { "__builtin_memcpy", builtin_memcpy, 3, memcpyt, VOID|PTR }, + { "__builtin_memset", builtin_memset, 3, memsett, VOID|PTR }, + { "__builtin_huge_valf", builtin_huge_valf, 0 }, + { "__builtin_huge_val", builtin_huge_val, 0 }, + { "__builtin_huge_vall", builtin_huge_vall, 0 }, + { "__builtin_inff", builtin_inff, 0 }, + { "__builtin_inf", builtin_inf, 0 }, + { "__builtin_infl", builtin_infl, 0 }, + { "__builtin_isgreater", builtin_isgreater, 2, NULL, INT }, + { "__builtin_isgreaterequal", builtin_isgreaterequal, 2, NULL, INT }, + { "__builtin_isless", builtin_isless, 2, NULL, INT }, + { "__builtin_islessequal", builtin_islessequal, 2, NULL, INT }, + { "__builtin_islessgreater", builtin_islessgreater, 2, NULL, INT }, + { "__builtin_isunordered", builtin_isunordered, 2, NULL, INT }, + { "__builtin_nanf", builtin_nanf, 1, nant, FLOAT }, + { "__builtin_nan", builtin_nan, 1, nant, DOUBLE }, + { "__builtin_nanl", builtin_nanl, 1, nant, LDOUBLE }, + { "__builtin_object_size", builtin_object_size, 2, memsett, SIZET }, + { "__builtin_strcmp", builtin_unimp, 2, strcmpt, INT }, + { "__builtin_strcpy", builtin_unimp, 2, strcmpt, CHAR|PTR }, + { "__builtin_strchr", builtin_unimp, 2, strchrt, CHAR|PTR }, + { "__builtin_strlen", builtin_unimp, 1, strcmpt, SIZET }, + { "__builtin_strrchr", builtin_unimp, 2, strchrt, CHAR|PTR }, + { "__builtin_strncpy", builtin_unimp, 3, strncpyt, CHAR|PTR }, + { "__builtin_strncat", builtin_unimp, 3, strncpyt, CHAR|PTR }, + { "__builtin_strcspn", builtin_unimp, 2, strcspnt, SIZET }, +#ifndef TARGET_STDARGS + { "__builtin_stdarg_start", builtin_stdarg_start, 2 }, + { "__builtin_va_start", builtin_stdarg_start, 2 }, + { "__builtin_va_arg", builtin_va_arg, 2 }, + { "__builtin_va_end", builtin_va_end, 1 }, + { "__builtin_va_copy", builtin_va_copy, 2 }, +#endif +#ifdef TARGET_BUILTINS + TARGET_BUILTINS +#endif +}; + +/* + * Check and cast arguments for builtins. + */ +static int +acnt(NODE *a, int narg, TWORD *tp) +{ + NODE *q; + TWORD t; + + if (a == NIL) + return narg; + for (; a->n_op == CM; a = a->n_left, narg--) { + if (tp == NULL) + continue; + q = a->n_right; + t = tp[narg-1]; + if (q->n_type == t) + continue; + a->n_right = ccast(q, t, 0, NULL, MKAP(BTYPE(t))); + } + + /* Last arg is ugly to deal with */ + if (narg == 1 && tp != NULL) { + q = talloc(); + *q = *a; + q = ccast(q, tp[0], 0, NULL, MKAP(BTYPE(tp[0]))); + *a = *q; + nfree(q); + } + return narg != 1; +} + +NODE * +builtin_check(NODE *f, NODE *a) +{ + const struct bitable *bt; + int i; + + for (i = 0; i < (int)(sizeof(bitable)/sizeof(bitable[0])); i++) { + bt = &bitable[i]; + if (strcmp(bt->name, f->n_sp->sname)) + continue; + if (bt->narg >= 0 && acnt(a, bt->narg, bt->tp)) { + uerror("wrong argument count to %s", bt->name); + return bcon(0); + } + return (*bt->fun)(f, a, bt->rt); + } + return NIL; +} +#endif diff --git a/compilers/pcc/pcc-1.0.0/cc/ccom/ccom.1 b/compilers/pcc/pcc-1.0.0/cc/ccom/ccom.1 new file mode 100644 index 00000000..2574907d --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/ccom/ccom.1 @@ -0,0 +1,192 @@ +.\" $NetBSD$ +.\" $Id: ccom.1,v 1.9 2010/04/05 13:13:57 reed Exp $ +.\" +.\" Copyright (c) 2007 Jeremy C. Reed +.\" Permission to use, copy, modify, and/or distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR AND CONTRIBUTORS DISCLAIM +.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHOR AND +.\" CONTRIBUTORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +.\" THIS SOFTWARE. +.Dd September 14, 2007 +.Dt CCOM 1 +.Os +.Sh NAME +.Nm ccom +.Nd C compiler +.Sh SYNOPSIS +.Nm +.Op Fl gs +.Op Fl W Ar flags +.Op Fl X Ar flags +.Op Fl x Ar optimizations +.Op Fl Z Ar flags +.Op infile +.Op outfile +.Sh DESCRIPTION +The +.Nm +utility provides a C compiler. +The frontend is usually +.Xr pcc 1 . +It is +.Em not +intended to be run directly. +.Pp +.Nm +reads the C source from +.Ar infile +or standard input and writes the assembler source +to +.Ar outfile +or to standard output. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl g +Enable debugging. +.\" built into binary, explain stabs? +.It Fl k +Generate PIC code. +.It Fl s +Print statistics to standard error when complete. +This includes: +name table entries, name string size, permanent allocated memory, +temporary allocated memory, lost memory, argument list unions, +dimension/function unions, struct/union/enum blocks, inline node count, +inline control blocks, and permanent symtab entries. +.\" TODO: explain units for above? +.It Fl v +Display version. +.It Fl W Ar flags +Report warnings. +(Do some basic checks.) +.Em NOTE! +.Em These are subject to change RSN! +.Ar flags +is one or more of the following: +.Bl -tag -width Ds +.It Sy error +Report all warnings as errors. +.It Sy implicit +Implies +.Sy implicit-function-declaration +and +.Sy implicit-int . +.It Sy implicit-function-declaration +Report if no prototype was declared for a function. +.It Sy implicit-int +TODO +.It Sy missing-prototypes +TODO +.It Sy strict-prototypes +TODO +.It Sy W +Enable all warnings. +.El +.\" +.It Fl X Ar flags +C specific debugging where +.Ar flags +is one or more of the following: +.Bl -tag -width Ds +.It Sy b +Building of parse trees +.It Sy d +Declarations (using multiple +.Sy d +flags gives more output) +.It Sy e +Pass1 trees at exit +.It Sy i +Initializations +.It Sy n +Memory allocations +.It Sy o +Turn off optimisations +.It Sy p +Prototypes +.It Sy s +Inlining +.It Sy t +Type conversions +.It Sy x +Target-specific flag, used in machine-dependent code +.El +.\" +.It Fl x Ar optimizations +.Ar optimizations +is one of the following: +.\" TODO: reword this, since multiple terms don't go with one -x switch?? +.Bl -tag -width deljumps +.It Sy deljumps +Delete redundant jumps and dead code. +.It Sy ssa +Convert statements into SSA form for optimization. +Not yet finished. +.It Sy tailcall +Currently not implemented. +.It Sy temps +Setting this flag allows variables to be put into registers, for further +optimization by the register allocator. +.El +The +.Fl x +flag can be passed multiple times to set different options. +.\" +.It Fl Z Ar flags +Code generator (pass2) specific debugging where +.Ar flags +is one or more of the following: +.Bl -tag -width Ds +.It Sy b +Basic block and SSA building +.It Sy c +Code printout +.It Sy e +Trees when entering pass2 +.It Sy f +Instruction matcher, may provide much output +.It Sy n +Memory allocation +.It Sy o +Instruction generator +.It Sy r +Register allocator +.It Sy s +Shape matching in instruction generator +.It Sy t +Type matching in instruction generator +.It Sy u +Sethi-Ullman computations +.It Sy x +Target-specific flag, used in machine-dependent code +.El +.El +.Sh SEE ALSO +.Xr as 1 , +.Xr cpp 1 , +.Xr pcc 1 +.Sh HISTORY +The +.Nm +compiler is based on the original Portable C Compiler by S. C. Johnson, +written in the late 70's. +Even though much of the compiler has been rewritten, some of the +basics still remain. +About 50% of the frontend code and 80% of the backend code has been +rewritten. +Most is written by Anders Magnusson, with the exception of +the data-flow analysis part and the SSA conversion code which is +written by Peter A Jonsson, and the Mips port that were written as +part of a project by undergraduate students at Lulea University of +Technology. +.Pp +This product includes software developed or owned by Caldera +International, Inc. diff --git a/compilers/pcc/pcc-1.0.0/cc/ccom/cgram.y b/compilers/pcc/pcc-1.0.0/cc/ccom/cgram.y new file mode 100644 index 00000000..ef489d36 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/ccom/cgram.y @@ -0,0 +1,2259 @@ +/* $Id: cgram.y,v 1.319 2011/01/27 18:00:32 ragge Exp $ */ + +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code and documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Comments for this grammar file. Ragge 021123 + * + * ANSI support required rewrite of the function header and declaration + * rules almost totally. + * + * The lex/yacc shared keywords are now split from the keywords used + * in the rest of the compiler, to simplify use of other frontends. + */ + +/* + * At last count, there were 5 shift/reduce and no reduce/reduce conflicts + * Four are accounted for; + * One is "dangling else" + * Two is in attribute parsing + * One is in ({ }) parsing + */ + +/* + * Token used in C lex/yacc communications. + */ +%token C_STRING /* a string constant */ +%token C_ICON /* an integer constant */ +%token C_FCON /* a floating point constant */ +%token C_NAME /* an identifier */ +%token C_TYPENAME /* a typedef'd name */ +%token C_ANDAND /* && */ +%token C_OROR /* || */ +%token C_GOTO /* unconditional goto */ +%token C_RETURN /* return from function */ +%token C_TYPE /* a type */ +%token C_CLASS /* a storage class */ +%token C_ASOP /* assignment ops */ +%token C_RELOP /* <=, <, >=, > */ +%token C_EQUOP /* ==, != */ +%token C_DIVOP /* /, % */ +%token C_SHIFTOP /* <<, >> */ +%token C_INCOP /* ++, -- */ +%token C_UNOP /* !, ~ */ +%token C_STROP /* ., -> */ +%token C_STRUCT +%token C_IF +%token C_ELSE +%token C_SWITCH +%token C_BREAK +%token C_CONTINUE +%token C_WHILE +%token C_DO +%token C_FOR +%token C_DEFAULT +%token C_CASE +%token C_SIZEOF +%token C_ALIGNOF +%token C_ENUM +%token C_ELLIPSIS +%token C_QUALIFIER +%token C_FUNSPEC +%token C_ASM +%token NOMATCH +%token C_TYPEOF /* COMPAT_GCC */ +%token C_ATTRIBUTE /* COMPAT_GCC */ +%token PCC_OFFSETOF + +/* + * Precedence + */ +%left ',' +%right '=' C_ASOP +%right '?' ':' +%left C_OROR +%left C_ANDAND +%left '|' +%left '^' +%left '&' +%left C_EQUOP +%left C_RELOP +%left C_SHIFTOP +%left '+' '-' +%left '*' C_DIVOP +%right C_UNOP +%right C_INCOP C_SIZEOF +%left '[' '(' C_STROP +%{ +# include "pass1.h" +# include +# include +# include + +int fun_inline; /* Reading an inline function */ +int oldstyle; /* Current function being defined */ +static struct symtab *xnf; +extern int enummer, tvaloff, inattr; +extern struct rstack *rpole; +static int widestr, alwinl; +NODE *cftnod; +static int attrwarn = 1; + +#define NORETYP SNOCREAT /* no return type, save in unused field in symtab */ + + NODE *bdty(int op, ...); +static void fend(void); +static void fundef(NODE *tp, NODE *p); +static void olddecl(NODE *p, NODE *a); +static struct symtab *init_declarator(NODE *tn, NODE *p, int assign, NODE *a); +static void resetbc(int mask); +static void swend(void); +static void addcase(NODE *p); +#ifdef GCC_COMPAT +static void gcccase(NODE *p, NODE *); +#endif +static void adddef(void); +static void savebc(void); +static void swstart(int, TWORD); +static void genswitch(int, TWORD, struct swents **, int); +static char *mkpstr(char *str); +static struct symtab *clbrace(NODE *); +static NODE *cmop(NODE *l, NODE *r); +static NODE *xcmop(NODE *out, NODE *in, NODE *str); +static void mkxasm(char *str, NODE *p); +static NODE *xasmop(char *str, NODE *p); +static int maxstlen(char *str); +static char *stradd(char *old, char *new); +static NODE *biop(int op, NODE *l, NODE *r); +static void flend(void); +static char * simname(char *s); +#ifdef GCC_COMPAT +static NODE *tyof(NODE *); /* COMPAT_GCC */ +static NODE *voidcon(void); /* COMPAT_GCC */ +#endif +static NODE *funargs(NODE *p); +static void oldargs(NODE *p); +static void uawarn(NODE *p, char *s); +static int con_e(NODE *p); +static void dainit(NODE *d, NODE *a); +static NODE *tymfix(NODE *p); +static NODE *namekill(NODE *p, int clr); +static NODE *aryfix(NODE *p); + +#define TYMFIX(inp) { \ + NODE *pp = inp; \ + inp = tymerge(pp->n_left, pp->n_right); \ + nfree(pp->n_left); nfree(pp); } +/* + * State for saving current switch state (when nested switches). + */ +struct savbc { + struct savbc *next; + int brklab; + int contlab; + int flostat; + int swx; +} *savbc, *savctx; + +%} + +%union { + int intval; + NODE *nodep; + struct symtab *symp; + struct rstack *rp; + char *strp; +} + + /* define types */ +%start ext_def_list + +%type ifelprefix ifprefix whprefix forprefix doprefix switchpart + xbegin +%type e .e term enum_dcl struct_dcl cast_type declarator + elist type_sq cf_spec merge_attribs + parameter_declaration abstract_declarator initializer + parameter_type_list parameter_list addrlbl + declaration_specifiers designation + specifier_qualifier_list merge_specifiers + identifier_list arg_param_list type_qualifier_list + designator_list designator xasm oplist oper cnstr funtype + typeof attribute attribute_specifier /* COMPAT_GCC */ + attribute_list attr_spec_list attr_var /* COMPAT_GCC */ +%type string C_STRING +%type str_head +%type xnfdeclarator clbrace enum_head + +%type C_STRUCT C_RELOP C_DIVOP C_SHIFTOP + C_ANDAND C_OROR C_STROP C_INCOP C_UNOP C_ASOP C_EQUOP + +%type C_TYPE C_QUALIFIER C_ICON C_FCON C_CLASS +%type C_NAME C_TYPENAME +%% + +ext_def_list: ext_def_list external_def + | { ftnend(); } + ; + +external_def: funtype kr_args compoundstmt { fend(); } + | declaration { blevel = 0; symclear(0); } + | asmstatement ';' + | ';' + | error { blevel = 0; } + ; + +funtype: /* no type given */ declarator { + fundef(mkty(INT, 0, MKAP(INT)), $1); + cftnsp->sflags |= NORETYP; + } + | declaration_specifiers declarator { fundef($1,$2); } + ; + +kr_args: /* empty */ + | arg_dcl_list + ; + +/* + * Returns a node pointer or NULL, if no types at all given. + * Type trees are checked for correctness and merged into one + * type node in typenode(). + */ +declaration_specifiers: + merge_attribs { $$ = typenode($1); } + ; + +merge_attribs: type_sq { $$ = $1; } + | type_sq merge_attribs { $$ = cmop($2, $1); } + | cf_spec { $$ = $1; } + | cf_spec merge_attribs { $$ = cmop($2, $1); } + ; + +type_sq: C_TYPE { $$ = $1; } + | C_TYPENAME { + struct symtab *sp = lookup($1, 0); + if (sp->stype == ENUMTY) { + sp->stype = strmemb(sp->sap)->stype; + } + $$ = mkty(sp->stype, sp->sdf, sp->sap); + $$->n_sp = sp; + } + | struct_dcl { $$ = $1; } + | enum_dcl { $$ = $1; } + | C_QUALIFIER { $$ = $1; } + | attribute_specifier { $$ = biop(ATTRIB, $1, 0); } + | typeof { $$ = $1; } + ; + +cf_spec: C_CLASS { $$ = $1; } + | C_FUNSPEC { fun_inline = 1; /* XXX - hack */ + $$ = block(QUALIFIER, NIL, NIL, 0, 0, 0); } + ; + +typeof: C_TYPEOF '(' term ')' { $$ = tyof(eve($3)); } + | C_TYPEOF '(' cast_type ')' { TYMFIX($3); $$ = tyof($3); } + ; + +attribute_specifier : + C_ATTRIBUTE '(' '(' attribute_list ')' ')' { $$ = $4; } + /*COMPAT_GCC*/ ; + +attribute_list: attribute + | attribute ',' attribute_list { $$ = cmop($3, $1); } + ; + +attribute: { +#ifdef GCC_COMPAT + $$ = voidcon(); +#endif + } + | C_NAME { $$ = bdty(NAME, $1); } + | C_NAME '(' elist ')' { + $$ = bdty($3 == NIL ? UCALL : CALL, bdty(NAME, $1), $3); + } + ; + +/* + * Adds a pointer list to front of the declarators. + */ +declarator: '*' declarator { $$ = bdty(UMUL, $2); } + | '*' type_qualifier_list declarator { + $$ = $2; + $$->n_left = $3; + } + | C_NAME { $$ = bdty(NAME, $1); } + | '(' attr_spec_list declarator ')' { + $$ = $3; + $$->n_ap = attr_add($$->n_ap, gcc_attr_parse($2)); + } + | '(' declarator ')' { $$ = $2; } + | declarator '[' e ']' { $$ = biop(LB, $1, $3); } + | declarator '[' C_CLASS e ']' { + if ($3->n_type != STATIC) + uerror("bad class keyword"); + tfree($3); /* XXX - handle */ + $$ = biop(LB, $1, $4); + } + | declarator '[' ']' { $$ = biop(LB, $1, bcon(NOOFFSET)); } + | declarator '[' '*' ']' { $$ = biop(LB, $1, bcon(NOOFFSET)); } + | declarator '(' parameter_type_list ')' { + $$ = bdty(CALL, $1, $3); + } + | declarator '(' identifier_list ')' { + $$ = bdty(CALL, $1, $3); + oldstyle = 1; + } + | declarator '(' ')' { $$ = bdty(UCALL, $1); } + ; + +type_qualifier_list: + C_QUALIFIER { $$ = $1; $$->n_op = UMUL; } + | type_qualifier_list C_QUALIFIER { + $$ = $1; + $$->n_qual |= $2->n_qual; + nfree($2); + } + | attribute_specifier { + $$ = block(UMUL, NIL, NIL, 0, 0, gcc_attr_parse($1)); + } + | type_qualifier_list attribute_specifier { + $1->n_ap = attr_add($1->n_ap, gcc_attr_parse($2)); + } + ; + +identifier_list: C_NAME { $$ = bdty(NAME, $1); oldargs($$); } + | identifier_list ',' C_NAME { + $$ = cmop($1, bdty(NAME, $3)); + oldargs($$->n_right); + } + ; + +/* + * Returns as parameter_list, but can add an additional ELLIPSIS node. + */ +parameter_type_list: + parameter_list { $$ = $1; } + | parameter_list ',' C_ELLIPSIS { + $$ = cmop($1, biop(ELLIPSIS, NIL, NIL)); + } + ; + +/* + * Returns a linked lists of nodes of op CM with parameters on + * its right and additional CM nodes of its left pointer. + * No CM nodes if only one parameter. + */ +parameter_list: parameter_declaration { $$ = $1; } + | parameter_list ',' parameter_declaration { + $$ = cmop($1, $3); + } + ; + +/* + * Returns a node pointer to the declaration. + */ +parameter_declaration: + declaration_specifiers declarator attr_var { + if ($1->n_lval != SNULL && $1->n_lval != REGISTER) + uerror("illegal parameter class"); + $$ = block(TYMERGE, $1, $2, INT, 0, gcc_attr_parse($3)); + } + | declaration_specifiers abstract_declarator { + $$ = block(TYMERGE, $1, $2, INT, 0, 0); + } + | declaration_specifiers { + $$ = block(TYMERGE, $1, bdty(NAME, NULL), INT, 0, 0); + } + ; + +abstract_declarator: + '*' { $$ = bdty(UMUL, bdty(NAME, NULL)); } + | '*' type_qualifier_list { + $$ = $2; + $$->n_left = bdty(NAME, NULL); + } + | '*' abstract_declarator { $$ = bdty(UMUL, $2); } + | '*' type_qualifier_list abstract_declarator { + $$ = $2; + $$->n_left = $3; + } + | '(' abstract_declarator ')' { $$ = $2; } + | '[' ']' attr_var { + $$ = block(LB, bdty(NAME, NULL), bcon(NOOFFSET), + INT, 0, gcc_attr_parse($3)); + } + | '[' e ']' attr_var { + $$ = block(LB, bdty(NAME, NULL), $2, + INT, 0, gcc_attr_parse($4)); + } + | abstract_declarator '[' ']' attr_var { + $$ = block(LB, $1, bcon(NOOFFSET), + INT, 0, gcc_attr_parse($4)); + } + | abstract_declarator '[' e ']' attr_var { + $$ = block(LB, $1, $3, INT, 0, gcc_attr_parse($5)); + } + | '(' ')' { $$ = bdty(UCALL, bdty(NAME, NULL)); } + | '(' ib2 parameter_type_list ')' { + $$ = bdty(CALL, bdty(NAME, NULL), $3); + } + | abstract_declarator '(' ')' { + $$ = bdty(UCALL, $1); + } + | abstract_declarator '(' ib2 parameter_type_list ')' { + $$ = bdty(CALL, $1, $4); + } + ; + +ib2: { } + ; +/* + * K&R arg declaration, between ) and { + */ +arg_dcl_list: arg_declaration + | arg_dcl_list arg_declaration + ; + + +arg_declaration: declaration_specifiers arg_param_list ';' { + nfree($1); + } + ; + +arg_param_list: declarator attr_var { + olddecl(block(TYMERGE, ccopy($0), $1, + INT, 0, 0), $2); + } + | arg_param_list ',' declarator attr_var { + olddecl(block(TYMERGE, ccopy($0), $3, + INT, 0, 0), $4); + } + ; + +/* + * Declarations in beginning of blocks. + */ +block_item_list: block_item + | block_item_list block_item + ; + +block_item: declaration + | statement + ; + +/* + * Here starts the old YACC code. + */ + +/* + * Variables are declared in init_declarator. + */ +declaration: declaration_specifiers ';' { tfree($1); fun_inline = 0; } + | declaration_specifiers init_declarator_list ';' { + tfree($1); + fun_inline = 0; + } + ; + +/* + * Normal declaration of variables. curtype contains the current type node. + * Returns nothing, variables are declared in init_declarator. + */ +init_declarator_list: + init_declarator { symclear(blevel); } + | init_declarator_list ',' attr_var { $$ = $0; } init_declarator { + uawarn($3, "init_declarator"); + symclear(blevel); + } + ; + +enum_dcl: enum_head '{' moe_list optcomma '}' { $$ = enumdcl($1); } + | C_ENUM C_NAME { $$ = enumref($2); } + ; + +enum_head: C_ENUM { $$ = enumhd(NULL); } + | C_ENUM C_NAME { $$ = enumhd($2); } + ; + +moe_list: moe + | moe_list ',' moe + ; + +moe: C_NAME { moedef($1); } + | C_TYPENAME { moedef($1); } + | C_NAME '=' e { enummer = con_e($3); moedef($1); } + | C_TYPENAME '=' e { enummer = con_e($3); moedef($1); } + ; + +struct_dcl: str_head '{' struct_dcl_list '}' { + NODE *p; + + $$ = dclstruct($1); + if (pragma_allpacked) { + p = bdty(CALL, bdty(NAME, "packed"), + bcon(pragma_allpacked)); + $$ = cmop(biop(ATTRIB, p, 0), $$); + } + } + | C_STRUCT attr_var C_NAME { + $$ = rstruct($3,$1); + uawarn($2, "struct_dcl"); + } + /*COMPAT_GCC*/ | str_head '{' '}' { $$ = dclstruct($1); } + ; + +attr_var: { + NODE *q, *p; + + p = pragma_aligned ? bdty(CALL, bdty(NAME, "aligned"), + bcon(pragma_aligned)) : NIL; + if (pragma_packed) { + q = bdty(NAME, "packed"); + p = (p == NIL ? q : cmop(p, q)); + } + pragma_aligned = pragma_packed = 0; + $$ = p; + } + /*COMPAT_GCC*/ | attr_spec_list + ; + +attr_spec_list: attribute_specifier + | attr_spec_list attribute_specifier { $$ = cmop($1, $2); } + ; + +str_head: C_STRUCT attr_var { $$ = bstruct(NULL, $1, $2); } + | C_STRUCT attr_var C_NAME { $$ = bstruct($3, $1, $2); } + ; + +struct_dcl_list: struct_declaration + | struct_dcl_list struct_declaration + ; + +struct_declaration: + specifier_qualifier_list struct_declarator_list optsemi { + tfree($1); + } + ; + +optsemi: ';' { } + | optsemi ';' { werror("extra ; in struct"); } + ; + +specifier_qualifier_list: + merge_specifiers { $$ = typenode($1); } + ; + +merge_specifiers: type_sq merge_specifiers { $$ = cmop($2, $1); } + | type_sq { $$ = $1; } + ; + +struct_declarator_list: + struct_declarator { symclear(blevel); } + | struct_declarator_list ',' { $$=$0; } + struct_declarator { symclear(blevel); } + ; + +struct_declarator: declarator attr_var { + NODE *p; + + $1 = aryfix($1); + p = tymerge($0, tymfix($1)); + if ($2) + p->n_ap = attr_add(p->n_ap, gcc_attr_parse($2)); + soumemb(p, (char *)$1->n_sp, 0); + tfree(p); + } + | ':' e { + int ie = con_e($2); + if (fldchk(ie)) + ie = 1; + falloc(NULL, ie, $0); + } + | declarator ':' e { + int ie = con_e($3); + if (fldchk(ie)) + ie = 1; + if ($1->n_op == NAME) { + /* XXX - tymfix() may alter $1 */ + tymerge($0, tymfix($1)); + soumemb($1, (char *)$1->n_sp, FIELD | ie); + nfree($1); + } else + uerror("illegal declarator"); + } + | declarator ':' e attr_spec_list { + int ie = con_e($3); + if (fldchk(ie)) + ie = 1; + if ($1->n_op == NAME) { + /* XXX - tymfix() may alter $1 */ + tymerge($0, tymfix($1)); + if ($4) + $1->n_ap = attr_add($1->n_ap, + gcc_attr_parse($4)); + soumemb($1, (char *)$1->n_sp, FIELD | ie); + nfree($1); + } else + uerror("illegal declarator"); + } + | /* unnamed member */ { + NODE *p = $0; + char *c = permalloc(10); + + if (p->n_type != STRTY && p->n_type != UNIONTY) + uerror("bad unnamed member type"); + snprintf(c, 10, "*%dFAKE", getlab()); + soumemb(p, c, 0); + } + ; + + /* always preceeded by attributes */ +xnfdeclarator: declarator attr_var { + $$ = xnf = init_declarator($0, $1, 1, $2); + } + | declarator C_ASM '(' string ')' { + pragma_renamed = newstring($4, strlen($4)); + $$ = xnf = init_declarator($0, $1, 1, NULL); + } + ; + +/* + * Handles declarations and assignments. + * Returns nothing. + */ +init_declarator: declarator attr_var { init_declarator($0, $1, 0, $2);} + | declarator C_ASM '(' string ')' attr_var { +#ifdef GCC_COMPAT + pragma_renamed = newstring($4, strlen($4)); + init_declarator($0, $1, 0, $6); +#else + werror("gcc extension"); + init_declarator($0, $1, 0, $6); +#endif + } + | xnfdeclarator '=' e { simpleinit($1, eve($3)); xnf = NULL; } + | xnfdeclarator '=' begbr init_list optcomma '}' { + endinit(); + xnf = NULL; + } + /*COMPAT_GCC*/ | xnfdeclarator '=' begbr '}' { endinit(); xnf = NULL; } + | xnfdeclarator '=' addrlbl { simpleinit($1, $3); xnf = NULL; } + ; + +begbr: '{' { beginit($-1); } + ; + +initializer: e %prec ',' { $$ = eve($1); } + | addrlbl { $$ = $1; } + | ibrace init_list optcomma '}' { $$ = NULL; } + | ibrace '}' { asginit(bcon(0)); $$ = NULL; } + ; + +init_list: designation initializer { dainit($1, $2); } + | init_list ',' designation initializer { dainit($3, $4); } + ; + +designation: designator_list '=' { desinit($1); $$ = NIL; } + | '[' e C_ELLIPSIS e ']' '=' { $$ = biop(CM, $2, $4); } + | { $$ = NIL; } + ; + +designator_list: designator { $$ = $1; } + | designator_list designator { $$ = $2; $$->n_left = $1; } + ; + +designator: '[' e ']' { + int ie = con_e($2); + if (ie < 0) { + uerror("designator must be non-negative"); + ie = 0; + } + $$ = biop(LB, NIL, bcon(ie)); + } + | C_STROP C_TYPENAME { + if ($1 != DOT) + uerror("invalid designator"); + $$ = bdty(NAME, $2); + } + | C_STROP C_NAME { + if ($1 != DOT) + uerror("invalid designator"); + $$ = bdty(NAME, $2); + } + ; + +optcomma : /* VOID */ + | ',' + ; + +ibrace: '{' { ilbrace(); } + ; + +/* STATEMENTS */ + +compoundstmt: begin block_item_list '}' { flend(); } + | begin '}' { flend(); } + ; + +begin: '{' { + struct savbc *bc = tmpalloc(sizeof(struct savbc)); + if (blevel == 1) { +#ifdef STABS + if (gflag) + stabs_line(lineno); +#endif + dclargs(); + } +#ifdef STABS + if (gflag && blevel > 1) + stabs_lbrac(blevel+1); +#endif + ++blevel; + oldstyle = 0; + bc->contlab = autooff; + bc->next = savctx; + savctx = bc; + bccode(); + if (!isinlining && sspflag && blevel == 2) + sspstart(); + } + ; + +statement: e ';' { ecomp(eve($1)); symclear(blevel); } + | compoundstmt + | ifprefix statement { plabel($1); reached = 1; } + | ifelprefix statement { + if ($1 != NOLAB) { + plabel( $1); + reached = 1; + } + } + | whprefix statement { + branch(contlab); + plabel( brklab ); + if( (flostat&FBRK) || !(flostat&FLOOP)) + reached = 1; + else + reached = 0; + resetbc(0); + } + | doprefix statement C_WHILE '(' e ')' ';' { + plabel(contlab); + if (flostat & FCONT) + reached = 1; + if (reached) + cbranch(buildtree(NE, eve($5), bcon(0)), + bcon($1)); + else + tfree(eve($5)); + plabel( brklab); + reached = 1; + resetbc(0); + } + | forprefix .e ')' statement + { plabel( contlab ); + if( flostat&FCONT ) reached = 1; + if( $2 ) ecomp( $2 ); + branch($1); + plabel( brklab ); + if( (flostat&FBRK) || !(flostat&FLOOP) ) reached = 1; + else reached = 0; + resetbc(0); + } + | switchpart statement + { if( reached ) branch( brklab ); + plabel( $1 ); + swend(); + plabel( brklab); + if( (flostat&FBRK) || !(flostat&FDEF) ) reached = 1; + resetbc(FCONT); + } + | C_BREAK ';' { + if (brklab == NOLAB) + uerror("illegal break"); + else if (reached) + branch(brklab); + flostat |= FBRK; + reached = 0; + } + | C_CONTINUE ';' { + if (contlab == NOLAB) + uerror("illegal continue"); + else + branch(contlab); + flostat |= FCONT; + goto rch; + } + | C_RETURN ';' { + branch(retlab); + if (cftnsp->stype != VOID && + (cftnsp->sflags & NORETYP) == 0 && + cftnsp->stype != VOID+FTN) + uerror("return value required"); + rch: + if (!reached) + warner(Wunreachable_code, NULL); + reached = 0; + } + | C_RETURN e ';' { + NODE *p, *q; + + p = nametree(cftnsp); + p->n_type = DECREF(p->n_type); + q = eve($2); +#ifndef NO_COMPLEX + if (ANYCX(q) || ANYCX(p)) + q = cxret(q, p); +#endif + p = buildtree(RETURN, p, q); + if (p->n_type == VOID) { + ecomp(p->n_right); + } else { + if (cftnod == NIL) + cftnod = tempnode(0, p->n_type, + p->n_df, p->n_ap); + ecomp(buildtree(ASSIGN, + ccopy(cftnod), p->n_right)); + } + tfree(p->n_left); + nfree(p); + branch(retlab); + reached = 0; + } + | C_GOTO C_NAME ';' { gotolabel($2); goto rch; } + | C_GOTO '*' e ';' { ecomp(biop(GOTO, eve($3), NIL)); } + | asmstatement ';' + | ';' + | error ';' + | error '}' + | label statement + ; + +asmstatement: C_ASM mvol '(' string ')' { send_passt(IP_ASM, mkpstr($4)); } + | C_ASM mvol '(' string xasm ')' { mkxasm($4, $5); } + ; + +mvol: /* empty */ + | C_QUALIFIER { nfree($1); } + ; + +xasm: ':' oplist { $$ = xcmop($2, NIL, NIL); } + | ':' oplist ':' oplist { $$ = xcmop($2, $4, NIL); } + | ':' oplist ':' oplist ':' cnstr { $$ = xcmop($2, $4, $6); } + ; + +oplist: /* nothing */ { $$ = NIL; } + | oper { $$ = $1; } + ; + +oper: string '(' e ')' { $$ = xasmop($1, eve($3)); } + | oper ',' string '(' e ')' { + $$ = cmop($1, xasmop($3, eve($5))); + } + ; + +cnstr: string { $$ = xasmop($1, bcon(0)); } + | cnstr ',' string { $$ = cmop($1, xasmop($3, bcon(0))); } + ; + +label: C_NAME ':' attr_var { deflabel($1, $3); reached = 1; } + | C_TYPENAME ':' attr_var { deflabel($1, $3); reached = 1; } + | C_CASE e ':' { addcase(eve($2)); reached = 1; } +/* COMPAT_GCC */| C_CASE e C_ELLIPSIS e ':' { +#ifdef GCC_COMPAT + gcccase(eve($2), eve($4)); reached = 1; +#endif + } + | C_DEFAULT ':' { reached = 1; adddef(); flostat |= FDEF; } + ; + +doprefix: C_DO { + savebc(); + brklab = getlab(); + contlab = getlab(); + plabel( $$ = getlab()); + reached = 1; + } + ; +ifprefix: C_IF '(' e ')' { + cbranch(buildtree(NOT, eve($3), NIL), bcon($$ = getlab())); + reached = 1; + } + ; +ifelprefix: ifprefix statement C_ELSE { + if (reached) + branch($$ = getlab()); + else + $$ = NOLAB; + plabel( $1); + reached = 1; + } + ; + +whprefix: C_WHILE '(' e ')' { + savebc(); + $3 = eve($3); + if ($3->n_op == ICON && $3->n_lval != 0) + flostat = FLOOP; + plabel( contlab = getlab()); + reached = 1; + brklab = getlab(); + if (flostat == FLOOP) + tfree($3); + else + cbranch(buildtree(NOT, $3, NIL), bcon(brklab)); + } + ; +forprefix: C_FOR '(' .e ';' .e ';' { + if ($3) + ecomp($3); + savebc(); + contlab = getlab(); + brklab = getlab(); + plabel( $$ = getlab()); + reached = 1; + if ($5) + cbranch(buildtree(NOT, $5, NIL), bcon(brklab)); + else + flostat |= FLOOP; + } + | C_FOR '(' { ++blevel; } declaration .e ';' { + blevel--; + savebc(); + contlab = getlab(); + brklab = getlab(); + plabel( $$ = getlab()); + reached = 1; + if ($5) + cbranch(buildtree(NOT, $5, NIL), bcon(brklab)); + else + flostat |= FLOOP; + } + ; + +switchpart: C_SWITCH '(' e ')' { + NODE *p; + int num; + TWORD t; + + savebc(); + brklab = getlab(); + $3 = eve($3); + if (($3->n_type != BOOL && $3->n_type > ULONGLONG) || + $3->n_type < CHAR) { + uerror("switch expression must have integer " + "type"); + t = INT; + } else { + $3 = intprom($3); + t = $3->n_type; + } + p = tempnode(0, t, 0, MKAP(t)); + num = regno(p); + ecomp(buildtree(ASSIGN, p, $3)); + branch( $$ = getlab()); + swstart(num, t); + reached = 0; + } + ; +/* EXPRESSIONS */ +.e: e { $$ = eve($1); } + | { $$=0; } + ; + +elist: { $$ = NIL; } + | e %prec ',' + | elist ',' e { $$ = biop(CM, $1, $3); } + | elist ',' cast_type { /* hack for stdarg */ + TYMFIX($3); + $3->n_op = TYPE; + $$ = biop(CM, $1, $3); + } + ; + +/* + * Precedence order of operators. + */ +e: e ',' e { $$ = biop(COMOP, $1, $3); } + | e '=' e { $$ = biop(ASSIGN, $1, $3); } + | e C_ASOP e { $$ = biop($2, $1, $3); } + | e '?' e ':' e { + $$=biop(QUEST, $1, biop(COLON, $3, $5)); + } + | e '?' ':' e { + NODE *p = tempnode(0, $1->n_type, $1->n_df, $1->n_ap); + $$ = biop(COLON, ccopy(p), $4); + $$=biop(QUEST, biop(ASSIGN, p, $1), $$); + } + | e C_OROR e { $$ = biop($2, $1, $3); } + | e C_ANDAND e { $$ = biop($2, $1, $3); } + | e '|' e { $$ = biop(OR, $1, $3); } + | e '^' e { $$ = biop(ER, $1, $3); } + | e '&' e { $$ = biop(AND, $1, $3); } + | e C_EQUOP e { $$ = biop($2, $1, $3); } + | e C_RELOP e { $$ = biop($2, $1, $3); } + | e C_SHIFTOP e { $$ = biop($2, $1, $3); } + | e '+' e { $$ = biop(PLUS, $1, $3); } + | e '-' e { $$ = biop(MINUS, $1, $3); } + | e C_DIVOP e { $$ = biop($2, $1, $3); } + | e '*' e { $$ = biop(MUL, $1, $3); } + | e '=' addrlbl { $$ = biop(ASSIGN, $1, $3); } + | term + ; + +xbegin: begin { + $$ = getlab(); getlab(); getlab(); + branch($$); plabel(($$)+1); } + ; + +addrlbl: C_ANDAND C_NAME { +#ifdef GCC_COMPAT + struct symtab *s = lookup($2, SLBLNAME); + if (s->soffset == 0) + s->soffset = -getlab(); + $$ = buildtree(ADDROF, nametree(s), NIL); +#else + uerror("gcc extension"); +#endif + } + ; + +term: term C_INCOP { $$ = biop($2, $1, bcon(1)); } + | '*' term { $$ = biop(UMUL, $2, NIL); } + | '&' term { $$ = biop(ADDROF, $2, NIL); } + | '-' term { $$ = biop(UMINUS, $2, NIL ); } + | '+' term { $$ = biop(PLUS, $2, bcon(0)); } + | C_UNOP term { $$ = biop($1, $2, NIL); } + | C_INCOP term { + $$ = biop($1 == INCR ? PLUSEQ : MINUSEQ, $2, bcon(1)); + } + | C_SIZEOF xa term { $$ = biop(SZOF, $3, bcon(0)); inattr = $2; } + | '(' cast_type ')' term %prec C_INCOP { + TYMFIX($2); + $$ = biop(CAST, $2, $4); + } + | C_SIZEOF xa '(' cast_type ')' %prec C_SIZEOF { + $$ = biop(SZOF, $4, bcon(1)); + inattr = $2; + } + | C_ALIGNOF xa '(' cast_type ')' { + TYMFIX($4); + int al = talign($4->n_type, $4->n_ap); + $$ = bcon(al/SZCHAR); + inattr = $2; + tfree($4); + } + | '(' cast_type ')' clbrace init_list optcomma '}' { + endinit(); + $$ = bdty(NAME, $4); + $$->n_op = CLOP; + } + | '(' cast_type ')' clbrace '}' { + endinit(); + $$ = bdty(NAME, $4); + $$->n_op = CLOP; + } + | term '[' e ']' { $$ = biop(LB, $1, $3); } + | C_NAME '(' elist ')' { + $$ = biop($3 ? CALL : UCALL, bdty(NAME, $1), $3); + } + | term '(' elist ')' { $$ = biop($3 ? CALL : UCALL, $1, $3); } + | term C_STROP C_NAME { $$ = biop($2, $1, bdty(NAME, $3)); } + | term C_STROP C_TYPENAME { $$ = biop($2, $1, bdty(NAME, $3));} + | C_NAME %prec C_SIZEOF /* below ( */{ $$ = bdty(NAME, $1); } + | PCC_OFFSETOF '(' cast_type ',' term ')' { + TYMFIX($3); + $3->n_type = INCREF($3->n_type); + $3 = biop(CAST, $3, bcon(0)); + if ($5->n_op == NAME) { + $$ = biop(STREF, $3, $5); + } else { + NODE *p = $5; + while (p->n_left->n_op != NAME) + p = p->n_left; + p->n_left = biop(STREF, $3, p->n_left); + $$ = $5; + } + $$ = biop(ADDROF, $$, NIL); + $3 = block(NAME, NIL, NIL, ENUNSIGN(INTPTR), 0, + MKAP(ENUNSIGN(INTPTR))); + $$ = biop(CAST, $3, $$); + } + | C_ICON { $$ = $1; } + | C_FCON { $$ = $1; } + | string { $$ = bdty(STRING, $1, widestr); } + | '(' e ')' { $$=$2; } + | '(' xbegin block_item_list e ';' '}' ')' { + /* XXX - check recursive ({ }) statements */ + branch(($2)+2); + plabel($2); + $$ = buildtree(COMOP, + biop(GOTO, bcon(($2)+1), NIL), eve($4)); + flend(); + } + | '(' xbegin block_item_list '}' ')' { + /* XXX - check recursive ({ }) statements */ + branch(($2)+2); + plabel($2); + $$ = buildtree(COMOP, + biop(GOTO, bcon(($2)+1), NIL), voidcon()); + flend(); + } + ; + +xa: { $$ = inattr; inattr = 0; } + ; + +clbrace: '{' { NODE *q = $-1; TYMFIX(q); $$ = clbrace(q); } + ; + +string: C_STRING { widestr = 0; $$ = stradd("", $1); } + | string C_STRING { $$ = stradd($1, $2); } + ; + +cast_type: specifier_qualifier_list { + $$ = biop(TYMERGE, $1, bdty(NAME, NULL)); + } + | specifier_qualifier_list abstract_declarator { + $$ = biop(TYMERGE, $1, aryfix($2)); + } + ; + +%% + +NODE * +mkty(TWORD t, union dimfun *d, struct attr *sue) +{ + return block(TYPE, NIL, NIL, t, d, sue); +} + +NODE * +bdty(int op, ...) +{ + va_list ap; + int val; + register NODE *q; + + va_start(ap, op); + q = biop(op, NIL, NIL); + + switch (op) { + case UMUL: + case UCALL: + q->n_left = va_arg(ap, NODE *); + q->n_rval = 0; + break; + + case CALL: + q->n_left = va_arg(ap, NODE *); + q->n_right = va_arg(ap, NODE *); + break; + + case LB: + q->n_left = va_arg(ap, NODE *); + if ((val = va_arg(ap, int)) <= 0) { + uerror("array size must be positive"); + val = 1; + } + q->n_right = bcon(val); + break; + + case NAME: + q->n_sp = va_arg(ap, struct symtab *); /* XXX survive tymerge */ + break; + + case STRING: + q->n_name = va_arg(ap, char *); + q->n_lval = va_arg(ap, int); + break; + + default: + cerror("bad bdty"); + } + va_end(ap); + + return q; +} + +static void +flend(void) +{ + if (!isinlining && sspflag && blevel == 2) + sspend(); +#ifdef STABS + if (gflag && blevel > 2) + stabs_rbrac(blevel); +#endif + --blevel; + if( blevel == 1 ) + blevel = 0; + symclear(blevel); /* Clean ut the symbol table */ + if (autooff > maxautooff) + maxautooff = autooff; + autooff = savctx->contlab; + savctx = savctx->next; +} + +static void +savebc(void) +{ + struct savbc *bc = tmpalloc(sizeof(struct savbc)); + + bc->brklab = brklab; + bc->contlab = contlab; + bc->flostat = flostat; + bc->next = savbc; + savbc = bc; + flostat = 0; +} + +static void +resetbc(int mask) +{ + flostat = savbc->flostat | (flostat&mask); + contlab = savbc->contlab; + brklab = savbc->brklab; + savbc = savbc->next; +} + +struct swdef { + struct swdef *next; /* Next in list */ + int deflbl; /* Label for "default" */ + struct swents *ents; /* Linked sorted list of case entries */ + int nents; /* # of entries in list */ + int num; /* Node value will end up in */ + TWORD type; /* Type of switch expression */ +} *swpole; + +/* + * add case to switch + */ +static void +addcase(NODE *p) +{ + struct swents **put, *w, *sw = tmpalloc(sizeof(struct swents)); + CONSZ val; + + p = optim(p); /* change enum to ints */ + if (p->n_op != ICON || p->n_sp != NULL) { + uerror( "non-constant case expression"); + return; + } + if (swpole == NULL) { + uerror("case not in switch"); + return; + } + + if (DEUNSIGN(swpole->type) != DEUNSIGN(p->n_type)) { + val = p->n_lval; + p = makety(p, swpole->type, 0, 0, MKAP(swpole->type)); + if (p->n_op != ICON) + cerror("could not cast case value to type of switch " + "expression"); + if (p->n_lval != val) + werror("case expression truncated"); + } + sw->sval = p->n_lval; + tfree(p); + put = &swpole->ents; + if (ISUNSIGNED(swpole->type)) { + for (w = swpole->ents; + w != NULL && (U_CONSZ)w->sval < (U_CONSZ)sw->sval; + w = w->next) + put = &w->next; + } else { + for (w = swpole->ents; w != NULL && w->sval < sw->sval; + w = w->next) + put = &w->next; + } + if (w != NULL && w->sval == sw->sval) { + uerror("duplicate case in switch"); + return; + } + plabel(sw->slab = getlab()); + *put = sw; + sw->next = w; + swpole->nents++; +} + +#ifdef GCC_COMPAT +void +gcccase(NODE *ln, NODE *hn) +{ + CONSZ i, l, h; + + l = icons(optim(ln)); + h = icons(optim(hn)); + + if (h < l) + i = l, l = h, h = i; + + for (i = l; i <= h; i++) + addcase(xbcon(i, NULL, hn->n_type)); +} +#endif + +/* + * add default case to switch + */ +static void +adddef(void) +{ + if (swpole == NULL) + uerror("default not inside switch"); + else if (swpole->deflbl != 0) + uerror("duplicate default in switch"); + else + plabel( swpole->deflbl = getlab()); +} + +static void +swstart(int num, TWORD type) +{ + struct swdef *sw = tmpalloc(sizeof(struct swdef)); + + sw->deflbl = sw->nents = 0; + sw->ents = NULL; + sw->next = swpole; + sw->num = num; + sw->type = type; + swpole = sw; +} + +/* + * end a switch block + */ +static void +swend(void) +{ + struct swents *sw, **swp; + int i; + + sw = tmpalloc(sizeof(struct swents)); + swp = tmpalloc(sizeof(struct swents *) * (swpole->nents+1)); + + sw->slab = swpole->deflbl; + swp[0] = sw; + + for (i = 1; i <= swpole->nents; i++) { + swp[i] = swpole->ents; + swpole->ents = swpole->ents->next; + } + genswitch(swpole->num, swpole->type, swp, swpole->nents); + + swpole = swpole->next; +} + +/* + * num: tempnode the value of the switch expression is in + * type: type of the switch expression + * + * p points to an array of structures, each consisting + * of a constant value and a label. + * The first is >=0 if there is a default label; + * its value is the label number + * The entries p[1] to p[n] are the nontrivial cases + * n is the number of case statements (length of list) + */ +static void +genswitch(int num, TWORD type, struct swents **p, int n) +{ + NODE *r, *q; + int i; + + if (mygenswitch(num, type, p, n)) + return; + + /* simple switch code */ + for (i = 1; i <= n; ++i) { + /* already in 1 */ + r = tempnode(num, type, 0, MKAP(type)); + q = xbcon(p[i]->sval, NULL, type); + r = buildtree(NE, r, clocal(q)); + cbranch(buildtree(NOT, r, NIL), bcon(p[i]->slab)); + } + if (p[0]->slab > 0) + branch(p[0]->slab); +} + +/* + * Declare a variable or prototype. + */ +static struct symtab * +init_declarator(NODE *tn, NODE *p, int assign, NODE *a) +{ + int class = tn->n_lval; + struct symtab *sp; + + p = aryfix(p); + p = tymerge(tn, p); + if (a) { + struct attr *ap = gcc_attr_parse(a); + p->n_ap = attr_add(p->n_ap, ap); + } + + p->n_sp = sp = lookup((char *)p->n_sp, 0); /* XXX */ + + if (fun_inline && ISFTN(p->n_type)) + sp->sflags |= SINLINE; + + if (ISFTN(p->n_type) == 0) { + if (assign) { + defid(p, class); + sp = p->n_sp; + sp->sflags |= SASG; + if (sp->sflags & SDYNARRAY) + uerror("can't initialize dynamic arrays"); + lcommdel(sp); + } else + nidcl(p, class); + } else { + extern NODE *parlink; + if (assign) + uerror("cannot initialise function"); + defid(p, uclass(class)); + sp = p->n_sp; + if (parlink) { + /* dynamic sized arrays in prototypes */ + tfree(parlink); /* Free delayed tree */ + parlink = NIL; + } + } + tfree(p); + return sp; +} + +/* + * Declare old-stype function arguments. + */ +static void +oldargs(NODE *p) +{ + blevel++; + p->n_op = TYPE; + p->n_type = FARG; + p->n_sp = lookup((char *)p->n_sp, 0);/* XXX */ + defid(p, PARAM); + blevel--; +} + +/* + * Set NAME nodes to a null name and index of LB nodes to NOOFFSET + * unless clr is one, in that case preserve variable name. + */ +static NODE * +namekill(NODE *p, int clr) +{ + NODE *q; + int o = p->n_op; + + switch (coptype(o)) { + case LTYPE: + if (o == NAME) { + if (clr) + p->n_sp = NULL; + else + p->n_sp = lookup((char *)p->n_sp, 0);/* XXX */ + } + break; + + case UTYPE: + p->n_left = namekill(p->n_left, clr); + break; + + case BITYPE: + p->n_left = namekill(p->n_left, clr); + if (o == LB) { + if (clr) { + tfree(p->n_right); + p->n_right = bcon(NOOFFSET); + } else + p->n_right = eve(p->n_right); + } else if (o == CALL) + p->n_right = namekill(p->n_right, 1); + else + p->n_right = namekill(p->n_right, clr); + if (o == TYMERGE) { + q = tymerge(p->n_left, p->n_right); + q->n_ap = attr_add(q->n_ap, p->n_ap); + tfree(p->n_left); + nfree(p); + p = q; + } + break; + } + return p; +} + +/* + * Declare function arguments. + */ +static NODE * +funargs(NODE *p) +{ + extern NODE *arrstk[10]; + + if (p->n_op == ELLIPSIS) + return p; + + p = namekill(p, 0); + if (ISFTN(p->n_type)) + p->n_type = INCREF(p->n_type); + if (ISARY(p->n_type)) { + p->n_type += (PTR-ARY); + if (p->n_df->ddim == -1) + tfree(arrstk[0]), arrstk[0] = NIL; + p->n_df++; + } + if (p->n_type == VOID && p->n_sp->sname == NULL) + return p; /* sanitycheck later */ + else if (p->n_sp->sname == NULL) + uerror("argument missing"); + else + defid(p, PARAM); + return p; +} + +static NODE * +listfw(NODE *p, NODE * (*f)(NODE *)) +{ + if (p->n_op == CM) { + p->n_left = listfw(p->n_left, f); + p->n_right = (*f)(p->n_right); + } else + p = (*f)(p); + return p; +} + + +/* + * Declare a function. + */ +static void +fundef(NODE *tp, NODE *p) +{ + extern int prolab; + struct symtab *s; + NODE *q, *typ; + int class = tp->n_lval, oclass, ctval; + char *c; + + /* + * We discard all names except for those needed for + * parameter declaration. While doing that, also change + * non-constant array sizes to unknown. + */ + ctval = tvaloff; + for (q = p; coptype(q->n_op) != LTYPE && + q->n_left->n_op != NAME; q = q->n_left) { + if (q->n_op == CALL) + q->n_right = namekill(q->n_right, 1); + } + if (q->n_op != CALL && q->n_op != UCALL) { + uerror("invalid function definition"); + p = bdty(UCALL, p); + } else if (q->n_op == CALL) { + blevel = 1; + argoff = ARGINIT; + if (oldstyle == 0) + q->n_right = listfw(q->n_right, funargs); + ftnarg(q); + blevel = 0; + } + + p = typ = tymerge(tp, p); + s = typ->n_sp = lookup((char *)typ->n_sp, 0); /* XXX */ + + oclass = s->sclass; + if (class == STATIC && oclass == EXTERN) + werror("%s was first declared extern, then static", s->sname); + + if (fun_inline) { + /* special syntax for inline functions */ + if (! strcmp(s->sname,"main")) + uerror("cannot inline main()"); + + s->sflags |= SINLINE; + inline_start(s); + if (class == EXTERN) + class = EXTDEF; + } else if (class == EXTERN) + class = SNULL; /* same result */ + + cftnsp = s; + defid(p, class); +#ifdef GCC_COMPAT + if (attr_find(p->n_ap, GCC_ATYP_ALW_INL)) { + /* Temporary turn on temps to make always_inline work */ + alwinl = 1; + if (xtemps == 0) alwinl |= 2; + xtemps = 1; + } +#endif + prolab = getlab(); + if ((c = cftnsp->soname) == NULL) + c = addname(exname(cftnsp->sname)); + send_passt(IP_PROLOG, -1, c, cftnsp->stype, + cftnsp->sclass == EXTDEF, prolab, ctval); + blevel++; +#ifdef STABS + if (gflag) + stabs_func(s); +#endif + tfree(tp); + tfree(p); + +} + +static void +fend(void) +{ + if (blevel) + cerror("function level error"); + ftnend(); + fun_inline = 0; + if (alwinl & 2) xtemps = 0; + alwinl = 0; + cftnsp = NULL; +} + +NODE * +structref(NODE *p, int f, char *name) +{ + NODE *r; + + if (f == DOT) + p = buildtree(ADDROF, p, NIL); + r = biop(NAME, NIL, NIL); + r->n_name = name; + r = buildtree(STREF, p, r); + return r; +} + +static void +olddecl(NODE *p, NODE *a) +{ + struct symtab *s; + + p = namekill(p, 0); + s = p->n_sp; + if (s->slevel != 1 || s->stype == UNDEF) + uerror("parameter '%s' not defined", s->sname); + else if (s->stype != FARG) + uerror("parameter '%s' redefined", s->sname); + + s->stype = p->n_type; + s->sdf = p->n_df; + s->sap = p->n_ap; + if (ISARY(s->stype)) { + s->stype += (PTR-ARY); + s->sdf++; + } + if (a) + attr_add(s->sap, gcc_attr_parse(a)); + nfree(p); +} + +void +branch(int lbl) +{ + int r = reached++; + ecomp(biop(GOTO, bcon(lbl), NIL)); + reached = r; +} + +/* + * Create a printable string based on an encoded string. + */ +static char * +mkpstr(char *str) +{ + char *s, *os; + int v, l = strlen(str)+3; /* \t + \n + \0 */ + + os = s = inlalloc(l); + *s++ = '\t'; + for (; *str; ) { + if (*str++ == '\\') + v = esccon(&str); + else + v = str[-1]; + *s++ = v; + } + *s++ = '\n'; + *s = 0; + return os; +} + +/* + * Estimate the max length a string will have in its internal + * representation based on number of \ characters. + */ +static int +maxstlen(char *str) +{ + int i; + + for (i = 0; *str; str++, i++) + if (*str == '\\' || *str < 32 || *str > 0176) + i += 3; + return i; +} + +static char * +voct(char *d, unsigned int v) +{ + v &= (1 << SZCHAR) - 1; + *d++ = '\\'; + *d++ = v/64 + '0'; v &= 077; + *d++ = v/8 + '0'; v &= 7; + *d++ = v + '0'; + return d; +} + + +/* + * Convert a string to internal format. The resulting string may be no + * more than len characters long. + */ +static void +fixstr(char *d, char *s, int len) +{ + unsigned int v; + + while (*s) { + if (len <= 0) + cerror("fixstr"); + if (*s == '\\') { + s++; + v = esccon(&s); + d = voct(d, v); + len -= 4; + } else if (*s < ' ' || *s > 0176) { + d = voct(d, *s++); + len -= 4; + } else + *d++ = *s++, len--; + } + *d = 0; +} + +/* + * Add "raw" string new to cleaned string old. + */ +static char * +stradd(char *old, char *new) +{ + char *rv; + int len; + + if (*new == 'L' && new[1] == '\"') + widestr = 1, new++; + if (*new == '\"') { + new++; /* remove first " */ + new[strlen(new) - 1] = 0;/* remove last " */ + } + len = strlen(old) + maxstlen(new) + 1; + rv = tmpalloc(len); + strlcpy(rv, old, len); + fixstr(rv + strlen(old), new, maxstlen(new) + 1); + return rv; +} + +/* + * Fake a symtab entry for compound literals. + */ +static struct symtab * +clbrace(NODE *p) +{ + struct symtab *sp; + + sp = getsymtab(simname("cl"), STEMP); + sp->stype = p->n_type; + sp->squal = p->n_qual; + sp->sdf = p->n_df; + sp->sap = p->n_ap; + tfree(p); + if (blevel == 0 && xnf != NULL) { + sp->sclass = STATIC; + sp->slevel = 2; + sp->soffset = getlab(); + } else { + sp->sclass = blevel ? AUTO : STATIC; + if (!ISARY(sp->stype) || sp->sdf->ddim != NOOFFSET) { + sp->soffset = NOOFFSET; + oalloc(sp, &autooff); + } + } + beginit(sp); + return sp; +} + +char * +simname(char *s) +{ + int len = strlen(s) + 10 + 1; + char *w = tmpalloc(len); + + snprintf(w, len, "%s%d", s, getlab()); + return w; +} + +NODE * +biop(int op, NODE *l, NODE *r) +{ + return block(op, l, r, INT, 0, MKAP(INT)); +} + +static NODE * +cmop(NODE *l, NODE *r) +{ + return biop(CM, l, r); +} + +static NODE * +voidcon(void) +{ + return block(ICON, NIL, NIL, STRTY, 0, MKAP(VOID)); +} + +/* Support for extended assembler a' la' gcc style follows below */ + +static NODE * +xmrg(NODE *out, NODE *in) +{ + NODE *p = in; + + if (p->n_op == XARG) { + in = cmop(out, p); + } else { + while (p->n_left->n_op == CM) + p = p->n_left; + p->n_left = cmop(out, p->n_left); + } + return in; +} + +/* + * Put together in and out node lists in one list, and balance it with + * the constraints on the right side of a CM node. + */ +static NODE * +xcmop(NODE *out, NODE *in, NODE *str) +{ + NODE *p, *q; + + if (out) { + /* D out-list sanity check */ + for (p = out; p->n_op == CM; p = p->n_left) { + q = p->n_right; + if (q->n_name[0] != '=' && q->n_name[0] != '+') + uerror("output missing ="); + } + if (p->n_name[0] != '=' && p->n_name[0] != '+') + uerror("output missing ="); + if (in == NIL) + p = out; + else + p = xmrg(out, in); + } else if (in) { + p = in; + } else + p = voidcon(); + + if (str == NIL) + str = voidcon(); + return cmop(p, str); +} + +/* + * Generate a XARG node based on a string and an expression. + */ +static NODE * +xasmop(char *str, NODE *p) +{ + + p = biop(XARG, p, NIL); + p->n_name = isinlining ? newstring(str, strlen(str)+1) : str; + return p; +} + +/* + * Generate a XASM node based on a string and an expression. + */ +static void +mkxasm(char *str, NODE *p) +{ + NODE *q; + + q = biop(XASM, p->n_left, p->n_right); + q->n_name = isinlining ? newstring(str, strlen(str)+1) : str; + nfree(p); + ecomp(q); +} + +#ifdef GCC_COMPAT +static NODE * +tyof(NODE *p) +{ + static struct symtab spp; + NODE *q = block(TYPE, NIL, NIL, p->n_type, p->n_df, p->n_ap); + q->n_qual = p->n_qual; + q->n_sp = &spp; /* for typenode */ + tfree(p); + return q; +} +#endif + +/* + * Traverse an unhandled expression tree bottom-up and call buildtree() + * or equivalent as needed. + */ +NODE * +eve(NODE *p) +{ + struct symtab *sp; + NODE *r, *p1, *p2; + int x; + + p1 = p->n_left; + p2 = p->n_right; + switch (p->n_op) { + case NAME: + sp = lookup((char *)p->n_sp, 0); + if (sp->sflags & SINLINE) + inline_ref(sp); + r = nametree(sp); + if (sp->sflags & SDYNARRAY) + r = buildtree(UMUL, r, NIL); +#ifdef GCC_COMPAT + if (attr_find(sp->sap, GCC_ATYP_DEPRECATED)) + werror("`%s' is deprecated", sp->sname); +#endif + break; + + case DOT: + case STREF: + r = structref(eve(p1), p->n_op, (char *)p2->n_sp); + nfree(p2); + break; + + case CAST: + p1 = buildtree(CAST, p1, eve(p2)); + nfree(p1->n_left); + r = p1->n_right; + nfree(p1); + break; + + + case SZOF: + x = xinline; xinline = 0; /* XXX hack */ + if (p2->n_lval == 0) + p1 = eve(p1); + else + TYMFIX(p1); + nfree(p2); + r = doszof(p1); + xinline = x; + break; + + case LB: + p1 = eve(p->n_left); + r = buildtree(UMUL, buildtree(PLUS, p1, eve(p2)), NIL); + break; + + case COMPL: +#ifndef NO_COMPLEX + p1 = eve(p1); + if (ANYCX(p1)) + r = cxconj(p1); + else + r = buildtree(COMPL, p1, NIL); + break; +#endif + case UMINUS: + case NOT: + case UMUL: + r = buildtree(p->n_op, eve(p->n_left), NIL); + break; + + case ADDROF: + r = eve(p1); + if (ISFTN(p->n_type)/* || ISARY(p->n_type) */){ +#ifdef notdef + werror( "& before array or function: ignored" ); +#endif + } else + r = buildtree(ADDROF, r, NIL); + break; + + case CALL: + p2 = eve(p2); + /* FALLTHROUGH */ + case UCALL: + if (p1->n_op == NAME) { + sp = lookup((char *)p1->n_sp, 0); + if (sp->stype == UNDEF) { + p1->n_type = FTN|INT; + p1->n_sp = sp; + p1->n_ap = MKAP(INT); + defid(p1, EXTERN); + } + nfree(p1); +#ifdef GCC_COMPAT + if (attr_find(sp->sap, GCC_ATYP_DEPRECATED)) + werror("`%s' is deprecated", sp->sname); +#endif + r = doacall(sp, nametree(sp), p2); + } else + r = doacall(NULL, eve(p1), p2); + break; + +#ifndef NO_COMPLEX + case XREAL: + case XIMAG: + p1 = eve(p1); + r = cxelem(p->n_op, p1); + break; +#endif + + case MUL: + case DIV: + case PLUS: + case MINUS: + case ASSIGN: + case EQ: + case NE: +#ifndef NO_COMPLEX + p1 = eve(p1); + p2 = eve(p2); + if (ANYCX(p1) || ANYCX(p2)) { + r = cxop(p->n_op, p1, p2); + } else if (ISITY(p1->n_type) || ISITY(p2->n_type)) { + r = imop(p->n_op, p1, p2); + } else + r = buildtree(p->n_op, p1, p2); + break; +#endif + case MOD: + case INCR: + case DECR: + case CM: + case GT: + case GE: + case LT: + case LE: + case RS: + case LS: + case RSEQ: + case LSEQ: + case AND: + case OR: + case ER: + case OROR: + case ANDAND: + case EREQ: + case OREQ: + case ANDEQ: + case MINUSEQ: + case PLUSEQ: + case MULEQ: + case DIVEQ: + case MODEQ: + case QUEST: + case COLON: + p1 = eve(p1); + r = buildtree(p->n_op, p1, eve(p2)); + break; + + case STRING: + r = strend(p->n_lval, p->n_name); + break; + + case COMOP: + if (p1->n_op == GOTO) { + /* inside ({ }), eve already called */ + r = buildtree(p->n_op, p1, p2); + } else { + p1 = eve(p1); + r = buildtree(p->n_op, p1, eve(p2)); + } + break; + + case TYPE: + case ICON: + case FCON: + case TEMP: + return p; + + case CLOP: + r = nametree(p->n_sp); + break; + + default: +#ifdef PCC_DEBUG + fwalk(p, eprint, 0); +#endif + cerror("eve"); + r = NIL; + } + nfree(p); + return r; +} + +int +con_e(NODE *p) +{ + return icons(eve(p)); +} + +void +uawarn(NODE *p, char *s) +{ + if (p == 0) + return; + if (attrwarn) + werror("unhandled %s attribute", s); + tfree(p); +} + +static void +dainit(NODE *d, NODE *a) +{ + if (d == NULL) { + asginit(a); + } else if (d->n_op == CM) { + int is = con_e(d->n_left); + int ie = con_e(d->n_right); + int i; + + nfree(d); + if (ie < is) + uerror("negative initializer range"); + desinit(biop(LB, NIL, bcon(is))); + for (i = is; i < ie; i++) + asginit(ccopy(a)); + asginit(a); + } else { + cerror("dainit"); + } +} + +/* + * Traverse down and tymerge() where appropriate. + */ +static NODE * +tymfix(NODE *p) +{ + NODE *q; + int o = coptype(p->n_op); + + switch (o) { + case LTYPE: + break; + case UTYPE: + p->n_left = tymfix(p->n_left); + break; + case BITYPE: + p->n_left = tymfix(p->n_left); + p->n_right = tymfix(p->n_right); + if (p->n_op == TYMERGE) { + q = tymerge(p->n_left, p->n_right); + q->n_ap = attr_add(q->n_ap, p->n_ap); + tfree(p->n_left); + nfree(p); + p = q; + } + break; + } + return p; +} + +static NODE * +aryfix(NODE *p) +{ + NODE *q; + + for (q = p; q->n_op != NAME; q = q->n_left) { + if (q->n_op == LB) { + q->n_right = optim(eve(q->n_right)); + if ((blevel == 0 || rpole != NULL) && + !nncon(q->n_right)) + uerror("array size not constant"); + /* + * Checks according to 6.7.5.2 clause 1: + * "...the expression shall have an integer type." + * "If the expression is a constant expression, + * it shall have a value greater than zero." + */ + if (!ISINTEGER(q->n_right->n_type)) + werror("array size is not an integer"); + else if (q->n_right->n_op == ICON && + q->n_right->n_lval < 0 && + q->n_right->n_lval != NOOFFSET) { + uerror("array size cannot be negative"); + q->n_right->n_lval = 1; + } + } else if (q->n_op == CALL) + q->n_right = namekill(q->n_right, 1); + } + return p; +} diff --git a/compilers/pcc/pcc-1.0.0/cc/ccom/gcc_compat.c b/compilers/pcc/pcc-1.0.0/cc/ccom/gcc_compat.c new file mode 100644 index 00000000..34f6a712 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/ccom/gcc_compat.c @@ -0,0 +1,574 @@ +/* $Id: gcc_compat.c,v 1.77 2011/02/01 14:20:02 ragge Exp $ */ +/* + * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Routines to support some of the gcc extensions to C. + */ +#ifdef GCC_COMPAT + +#include "pass1.h" +#include "cgram.h" + +#include + +static struct kw { + char *name, *ptr; + int rv; +} kw[] = { +/* + * Do NOT change the order of these entries unless you know + * what you're doing! + */ +/* 0 */ { "__asm", NULL, C_ASM }, +/* 1 */ { "__signed", NULL, 0 }, +/* 2 */ { "__inline", NULL, C_FUNSPEC }, +/* 3 */ { "__const", NULL, 0 }, +/* 4 */ { "__asm__", NULL, C_ASM }, +/* 5 */ { "__inline__", NULL, C_FUNSPEC }, +/* 6 */ { "__thread", NULL, 0 }, +/* 7 */ { "__FUNCTION__", NULL, 0 }, +/* 8 */ { "__volatile", NULL, 0 }, +/* 9 */ { "__volatile__", NULL, 0 }, +/* 10 */{ "__restrict", NULL, -1 }, +/* 11 */{ "__typeof__", NULL, C_TYPEOF }, +/* 12 */{ "typeof", NULL, C_TYPEOF }, +/* 13 */{ "__extension__", NULL, -1 }, +/* 14 */{ "__signed__", NULL, 0 }, +/* 15 */{ "__attribute__", NULL, 0 }, +/* 16 */{ "__attribute", NULL, 0 }, +/* 17 */{ "__real__", NULL, 0 }, +/* 18 */{ "__imag__", NULL, 0 }, +/* 19 */{ "__builtin_offsetof", NULL, PCC_OFFSETOF }, +/* 20 */{ "__PRETTY_FUNCTION__", NULL, 0 }, +/* 21 */{ "__alignof__", NULL, C_ALIGNOF }, +/* 22 */{ "__typeof", NULL, C_TYPEOF }, +/* 23 */{ "__alignof", NULL, C_ALIGNOF }, +/* 24 */{ "__restrict__", NULL, -1 }, + { NULL, NULL, 0 }, +}; + +/* g77 stuff */ +#if SZFLOAT == SZLONG +#define G77_INTEGER LONG +#define G77_UINTEGER ULONG +#elif SZFLOAT == SZINT +#define G77_INTEGER INT +#define G77_UINTEGER UNSIGNED +#else +#error fix g77 stuff +#endif +#if SZFLOAT*2 == SZLONG +#define G77_LONGINT LONG +#define G77_ULONGINT ULONG +#elif SZFLOAT*2 == SZLONGLONG +#define G77_LONGINT LONGLONG +#define G77_ULONGINT ULONGLONG +#else +#error fix g77 long stuff +#endif + +static TWORD g77t[] = { G77_INTEGER, G77_UINTEGER, G77_LONGINT, G77_ULONGINT }; +static char *g77n[] = { "__g77_integer", "__g77_uinteger", + "__g77_longint", "__g77_ulongint" }; + +void +gcc_init() +{ + struct kw *kwp; + NODE *p; + TWORD t; + int i; + + for (kwp = kw; kwp->name; kwp++) + kwp->ptr = addname(kwp->name); + + for (i = 0; i < 4; i++) { + struct symtab *sp; + t = ctype(g77t[i]); + p = block(NAME, NIL, NIL, t, NULL, MKAP(t)); + sp = lookup(addname(g77n[i]), 0); + p->n_sp = sp; + defid(p, TYPEDEF); + nfree(p); + } + +} + +#define TS "\n#pragma tls\n# %d\n" +#define TLLEN sizeof(TS)+10 +/* + * See if a string matches a gcc keyword. + */ +int +gcc_keyword(char *str, NODE **n) +{ + extern int inattr, parlvl, parbal; + YYSTYPE *yyl = (YYSTYPE *)n; /* XXX should pass yylval */ + char tlbuf[TLLEN], *tw; + struct kw *kwp; + int i; + + /* XXX hack, should pass everything in expressions */ + if (str == kw[21].ptr) + return kw[21].rv; + + if (inattr) + return 0; + + for (i = 0, kwp = kw; kwp->name; kwp++, i++) + if (str == kwp->ptr) + break; + if (kwp->name == NULL) + return 0; + if (kwp->rv) + return kwp->rv; + switch (i) { + case 1: /* __signed */ + case 14: /* __signed__ */ + *n = mkty((TWORD)SIGNED, 0, MKAP(SIGNED)); + return C_TYPE; + case 3: /* __const */ + *n = block(QUALIFIER, NIL, NIL, CON, 0, 0); + (*n)->n_qual = CON; + return C_QUALIFIER; + case 6: /* __thread */ + snprintf(tlbuf, TLLEN, TS, lineno); + tw = &tlbuf[strlen(tlbuf)]; + while (tw > tlbuf) + cunput(*--tw); + return -1; + case 7: /* __FUNCTION__ */ + case 20: /* __PRETTY_FUNCTION__ */ + if (cftnsp == NULL) { + uerror("%s outside function", kwp->name); + yylval.strp = ""; + } else + yylval.strp = cftnsp->sname; /* XXX - not C99 */ + return C_STRING; + case 8: /* __volatile */ + case 9: /* __volatile__ */ + *n = block(QUALIFIER, NIL, NIL, VOL, 0, 0); + (*n)->n_qual = VOL; + return C_QUALIFIER; + case 15: /* __attribute__ */ + case 16: /* __attribute */ + inattr = 1; + parlvl = parbal; + return C_ATTRIBUTE; + case 17: /* __real__ */ + yyl->intval = XREAL; + return C_UNOP; + case 18: /* __imag__ */ + yyl->intval = XIMAG; + return C_UNOP; + } + cerror("gcc_keyword"); + return 0; +} + +#ifndef TARGET_ATTR +#define TARGET_ATTR(p, sue) 0 +#endif +#ifndef ALMAX +#define ALMAX (ALLDOUBLE > ALLONGLONG ? ALLDOUBLE : ALLONGLONG) +#endif + +/* allowed number of args */ +#define A_0ARG 0x01 +#define A_1ARG 0x02 +#define A_2ARG 0x04 +#define A_3ARG 0x08 +/* arg # is a name */ +#define A1_NAME 0x10 +#define A2_NAME 0x20 +#define A3_NAME 0x40 +#define A_MANY 0x80 +/* arg # is "string" */ +#define A1_STR 0x100 +#define A2_STR 0x200 +#define A3_STR 0x400 + +#ifdef __MSC__ +#define CS(x) +#else +#define CS(x) [x] = +#endif + +struct atax { + int typ; + char *name; +} atax[GCC_ATYP_MAX] = { + CS(ATTR_NONE) { 0, NULL }, + CS(ATTR_COMPLEX) { 0, NULL }, + CS(ATTR_BASETYP) { 0, NULL }, + CS(ATTR_QUALTYP) { 0, NULL }, + CS(ATTR_STRUCT) { 0, NULL }, + CS(GCC_ATYP_ALIGNED) { A_0ARG|A_1ARG, "aligned" }, + CS(GCC_ATYP_PACKED) { A_0ARG|A_1ARG, "packed" }, + CS(GCC_ATYP_SECTION) { A_1ARG|A1_STR, "section" }, + CS(GCC_ATYP_TRANSP_UNION) { A_0ARG, "transparent_union" }, + CS(GCC_ATYP_UNUSED) { A_0ARG, "unused" }, + CS(GCC_ATYP_DEPRECATED) { A_0ARG, "deprecated" }, + CS(GCC_ATYP_MAYALIAS) { A_0ARG, "may_alias" }, + CS(GCC_ATYP_MODE) { A_1ARG|A1_NAME, "mode" }, + CS(GCC_ATYP_NORETURN) { A_0ARG, "noreturn" }, + CS(GCC_ATYP_FORMAT) { A_3ARG|A1_NAME, "format" }, + CS(GCC_ATYP_NONNULL) { A_MANY, "nonnull" }, + CS(GCC_ATYP_SENTINEL) { A_0ARG|A_1ARG, "sentinel" }, + CS(GCC_ATYP_WEAK) { A_0ARG, "weak" }, + CS(GCC_ATYP_FORMATARG) { A_1ARG, "format_arg" }, + CS(GCC_ATYP_GNU_INLINE) { A_0ARG, "gnu_inline" }, + CS(GCC_ATYP_MALLOC) { A_0ARG, "malloc" }, + CS(GCC_ATYP_NOTHROW) { A_0ARG, "nothrow" }, + CS(GCC_ATYP_CONST) { A_0ARG, "const" }, + CS(GCC_ATYP_PURE) { A_0ARG, "pure" }, + CS(GCC_ATYP_CONSTRUCTOR) { A_0ARG, "constructor" }, + CS(GCC_ATYP_DESTRUCTOR) { A_0ARG, "destructor" }, + CS(GCC_ATYP_VISIBILITY) { A_1ARG|A1_STR, "visibility" }, + CS(GCC_ATYP_STDCALL) { A_0ARG, "stdcall" }, + CS(GCC_ATYP_CDECL) { A_0ARG, "cdecl" }, + CS(GCC_ATYP_WARN_UNUSED_RESULT) { A_0ARG, "warn_unused_result" }, + CS(GCC_ATYP_USED) { A_0ARG, "used" }, + CS(GCC_ATYP_NO_INSTR_FUN) { A_0ARG, "no_instrument_function" }, + CS(GCC_ATYP_NOINLINE) { A_0ARG, "noinline" }, + CS(GCC_ATYP_ALIAS) { A_1ARG|A1_STR, "alias" }, + CS(GCC_ATYP_WEAKREF) { A_0ARG|A_1ARG|A1_STR, "weakref" }, + CS(GCC_ATYP_ALLOCSZ) { A_1ARG|A_2ARG, "alloc_size" }, + CS(GCC_ATYP_ALW_INL) { A_0ARG, "always_inline" }, + CS(GCC_ATYP_TLSMODEL) { A_1ARG|A1_STR, "tls_model" }, + CS(GCC_ATYP_ALIASWEAK) { A_1ARG|A1_STR, "aliasweak" }, + + CS(GCC_ATYP_BOUNDED) { A_3ARG|A_MANY|A1_NAME, "bounded" }, +}; + +#if SZPOINT(CHAR) == SZLONGLONG +#define GPT LONGLONG +#else +#define GPT INT +#endif + +struct atax mods[] = { + { 0, NULL }, + { INT, "SI" }, + { INT, "word" }, + { GPT, "pointer" }, + { CHAR, "byte" }, + { CHAR, "QI" }, + { SHORT, "HI" }, + { LONGLONG, "DI" }, + { FLOAT, "SF" }, + { DOUBLE, "DF" }, + { LDOUBLE, "XF" }, + { FCOMPLEX, "SC" }, + { COMPLEX, "DC" }, + { LCOMPLEX, "XC" }, +#ifdef TARGET_MODS + TARGET_MODS +#endif +}; +#define ATSZ (sizeof(mods)/sizeof(mods[0])) + +static int +amatch(char *s, struct atax *at, int mx) +{ + int i, len; + + if (s[0] == '_' && s[1] == '_') + s += 2; + len = strlen(s); + if (len > 2 && s[len-1] == '_' && s[len-2] == '_') + len -= 2; + for (i = 0; i < mx; i++) { + char *t = at[i].name; + if (t != NULL && strncmp(s, t, len) == 0 && t[len] == 0) + return i; + } + return 0; +} + +static void +setaarg(int str, union aarg *aa, NODE *p) +{ + if (str) { + if (((str & (A1_STR|A2_STR|A3_STR)) && p->n_op != STRING) || + ((str & (A1_NAME|A2_NAME|A3_NAME)) && p->n_op != NAME)) + uerror("bad arg to attribute"); + if (p->n_op == STRING) { + aa->sarg = newstring(p->n_name, strlen(p->n_name)+1); + } else + aa->sarg = (char *)p->n_sp; + nfree(p); + } else + aa->iarg = (int)icons(eve(p)); +} + +/* + * Parse attributes from an argument list. + */ +static struct attr * +gcc_attribs(NODE *p) +{ + NODE *q, *r; + struct attr *ap; + char *name = NULL, *c; + int cw, attr, narg, i; + + if (p->n_op == NAME) { + name = (char *)p->n_sp; + } else if (p->n_op == CALL || p->n_op == UCALL) { + name = (char *)p->n_left->n_sp; + } else if (p->n_op == ICON && p->n_type == STRTY) { + return NULL; + } else + cerror("bad variable attribute"); + + if ((attr = amatch(name, atax, GCC_ATYP_MAX)) == 0) { + werror("unsupported attribute '%s'", name); + ap = NULL; + goto out; + } + narg = 0; + if (p->n_op == CALL) + for (narg = 1, q = p->n_right; q->n_op == CM; q = q->n_left) + narg++; + + cw = atax[attr].typ; + if (!(cw & A_MANY) && ((narg > 3) || ((cw & (1 << narg)) == 0))) { + uerror("wrong attribute arg count"); + return NULL; + } + ap = attr_new(attr, 3); /* XXX should be narg */ + q = p->n_right; + + switch (narg) { + default: + /* XXX */ + while (narg-- > 3) { + r = q; + q = q->n_left; + tfree(r->n_right); + nfree(r); + } + /* FALLTHROUGH */ + case 3: + setaarg(cw & (A3_NAME|A3_STR), &ap->aa[2], q->n_right); + r = q; + q = q->n_left; + nfree(r); + /* FALLTHROUGH */ + case 2: + setaarg(cw & (A2_NAME|A2_STR), &ap->aa[1], q->n_right); + r = q; + q = q->n_left; + nfree(r); + /* FALLTHROUGH */ + case 1: + setaarg(cw & (A1_NAME|A1_STR), &ap->aa[0], q); + p->n_op = UCALL; + /* FALLTHROUGH */ + case 0: + break; + } + + /* some attributes must be massaged special */ + switch (attr) { + case GCC_ATYP_ALIGNED: + if (narg == 0) + ap->aa[0].iarg = ALMAX; + else + ap->aa[0].iarg *= SZCHAR; + break; + case GCC_ATYP_PACKED: + if (narg == 0) + ap->aa[0].iarg = 1; /* bitwise align */ + else + ap->aa[0].iarg *= SZCHAR; + break; + + case GCC_ATYP_MODE: + if ((i = amatch(ap->aa[0].sarg, mods, ATSZ)) == 0) + werror("unknown mode arg %s", ap->aa[0].sarg); + ap->aa[0].iarg = ctype(mods[i].typ); + break; + + case GCC_ATYP_VISIBILITY: + c = ap->aa[0].sarg; + if (strcmp(c, "default") && strcmp(c, "hidden") && + strcmp(c, "internal") && strcmp(c, "protected")) + werror("unknown visibility %s", c); + break; + + case GCC_ATYP_TLSMODEL: + c = ap->aa[0].sarg; + if (strcmp(c, "global-dynamic") && strcmp(c, "local-dynamic") && + strcmp(c, "initial-exec") && strcmp(c, "local-exec")) + werror("unknown tls model %s", c); + break; + + default: + break; + } +out: + return ap; +} + +/* + * Extract attributes from a node tree and return attribute entries + * based on its contents. + */ +struct attr * +gcc_attr_parse(NODE *p) +{ + struct attr *b, *c; + + if (p == NIL) + return NULL; + + if (p->n_op != CM) { + b = gcc_attribs(p); + tfree(p); + } else { + b = gcc_attr_parse(p->n_left); + c = gcc_attr_parse(p->n_right); + nfree(p); + b = b ? attr_add(b, c) : c; + } + return b; +} + +/* + * Fixup struct/unions depending on attributes. + */ +void +gcc_tcattrfix(NODE *p) +{ + struct symtab *sp; + struct attr *ap; + int sz, coff, csz, al; + + if ((ap = attr_find(p->n_ap, GCC_ATYP_PACKED)) == NULL) + return; /* nothing to fix */ + + al = ap->iarg(0); + + /* Must repack struct */ + coff = csz = 0; + for (sp = strmemb(ap); sp; sp = sp->snext) { + if (sp->sclass & FIELD) + sz = sp->sclass&FLDSIZ; + else + sz = (int)tsize(sp->stype, sp->sdf, sp->sap); + SETOFF(sz, al); + sp->soffset = coff; + coff += sz; + if (coff > csz) + csz = coff; + if (p->n_type == UNIONTY) + coff = 0; + } + SETOFF(csz, al); /* Roundup to whatever */ + + ap = attr_find(p->n_ap, ATTR_BASETYP); + ap->atypsz = csz; + ap->aalign = al; +} + +/* + * gcc-specific pragmas. + */ +int +pragmas_gcc(char *t) +{ + int ign, warn, err, i, u; + extern bittype warnary[], werrary[]; + extern char *flagstr[], *pragstore; + + if (strcmp((t = pragtok(NULL)), "diagnostic") == 0) { + ign = warn = err = 0; + if (strcmp((t = pragtok(NULL)), "ignored") == 0) + ign = 1; + else if (strcmp(t, "warning") == 0) + warn = 1; + else if (strcmp(t, "error") == 0) + err = 1; + else + return 1; + if (eat('\"') || eat('-')) + return 1; + for (t = pragstore; *t && *t != '\"'; t++) + ; + u = *t; + *t = 0; + for (i = 0; i < NUMW; i++) { + if (strcmp(flagstr[i], pragstore+1) != 0) + continue; + if (err) { + BITSET(warnary, i); + BITSET(werrary, i); + } else if (warn) { + BITSET(warnary, i); + BITCLEAR(werrary, i); + } else { + BITCLEAR(warnary, i); + BITCLEAR(werrary, i); + } + return 0; + } + *t = u; + } else if (strcmp(t, "poison") == 0) { + /* currently ignore */; + } else if (strcmp(t, "visibility") == 0) { + /* currently ignore */; + } else + werror("gcc pragma unsupported"); + return 0; +} + +#ifdef PCC_DEBUG +void +dump_attr(struct attr *ap) +{ + printf("attributes; "); + for (; ap; ap = ap->next) { + if (ap->atype >= GCC_ATYP_MAX) { + printf("bad type %d, ", ap->atype); + } else if (atax[ap->atype].name == 0) { + char *c = ap->atype == ATTR_COMPLEX ? "complex" : + ap->atype == ATTR_BASETYP ? "basetyp" : + ap->atype == ATTR_STRUCT ? "struct" : "badtype"; + printf("%s, ", c); + } else { + printf("%s: ", atax[ap->atype].name); + printf("%d %d %d, ", ap->iarg(0), + ap->iarg(1), ap->iarg(2)); + } + } + printf("\n"); +} +#endif +#endif diff --git a/compilers/pcc/pcc-1.0.0/cc/ccom/init.c b/compilers/pcc/pcc-1.0.0/cc/ccom/init.c new file mode 100644 index 00000000..17e6f9d9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/ccom/init.c @@ -0,0 +1,1060 @@ +/* $Id: init.c,v 1.62 2011/02/19 17:23:39 ragge Exp $ */ + +/* + * Copyright (c) 2004, 2007 Anders Magnusson (ragge@ludd.ltu.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code and documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "pass1.h" +#include + +/* + * The following machine-dependent routines may be called during + * initialization: + * + * zbits(OFFSZ, int) - sets int bits of zero at position OFFSZ. + * infld(CONSZ off, int fsz, CONSZ val) + * - sets the bitfield val starting at off and size fsz. + * ninval(CONSZ off, int fsz, NODE *) + * - prints an integer constant which may have + * a label associated with it, located at off and + * size fsz. + * + * Initialization may be of different kind: + * - Initialization at compile-time, all values are constants and laid + * out in memory. Static or extern variables outside functions. + * - Initialization at run-time, written to their values as code. + * + * Currently run-time-initialized variables are only initialized by using + * move instructions. An optimization might be to detect that it is + * initialized with constants and therefore copied from readonly memory. + */ + +/* + * The base element(s) of an initialized variable is kept in a linked + * list, allocated while initialized. + * + * When a scalar is found, entries are popped of the instk until it's + * possible to find an entry for a new scalar; then onstk() is called + * to get the correct type and size of that scalar. + * + * If a right brace is found, pop the stack until a matching left brace + * were found while filling the elements with zeros. This left brace is + * also marking where the current level is for designated initializations. + * + * Position entries are increased when traversing back down into the stack. + */ + +/* + * Good-to-know entries from symtab: + * soffset - # of bits from beginning of this structure. + */ + +/* + * TO FIX: + * - Alignment of structs on like i386 char members. + */ + +int idebug; + +/* + * Struct used in array initialisation. + */ +static struct instk { + struct instk *in_prev; /* linked list */ + struct symtab *in_lnk; /* member in structure initializations */ + struct symtab *in_sym; /* symtab index */ + union dimfun *in_df; /* dimenston of array */ + TWORD in_t; /* type for this level */ + int in_n; /* number of arrays seen so far */ + int in_fl; /* flag which says if this level is controlled by {} */ +} *pstk, pbase; + +static struct symtab *csym; + +#ifdef PCC_DEBUG +static void prtstk(struct instk *in); +#endif + +/* + * Linked lists for initializations. + */ +struct ilist { + struct ilist *next; + CONSZ off; /* bit offset of this entry */ + int fsz; /* bit size of this entry */ + NODE *n; /* node containing this data info */ +}; + +struct llist { + SLIST_ENTRY(llist) next; + CONSZ begsz; /* bit offset of this entry */ + struct ilist *il; +}; +static SLIST_HEAD(llh, llist) lpole; +static CONSZ basesz; +static int numents; /* # of array entries allocated */ + +static struct initctx { + struct initctx *prev; + struct instk *pstk; + struct symtab *psym; + struct llh lpole; + CONSZ basesz; + int numents; +} *inilnk; + +static struct ilist * +getil(struct ilist *next, CONSZ b, int sz, NODE *n) +{ + struct ilist *il = tmpalloc(sizeof(struct ilist)); + + il->off = b; + il->fsz = sz; + il->n = n; + il->next = next; + return il; +} + +/* + * Allocate a new struct defining a block of initializers appended to the + * end of the llist. Return that entry. + */ +static struct llist * +getll(void) +{ + struct llist *ll; + + ll = tmpalloc(sizeof(struct llist)); + ll->begsz = numents * basesz; + ll->il = NULL; + SLIST_INSERT_LAST(&lpole, ll, next); + numents++; + return ll; +} + +/* + * Return structure containing off bitnumber. + * Allocate more entries, if needed. + */ +static struct llist * +setll(OFFSZ off) +{ + struct llist *ll = NULL; + + /* Ensure that we have enough entries */ + while (off >= basesz * numents) + ll = getll(); + + if (ll != NULL && ll->begsz <= off && ll->begsz + basesz > off) + return ll; + + SLIST_FOREACH(ll, &lpole, next) + if (ll->begsz <= off && ll->begsz + basesz > off) + break; + return ll; /* ``cannot fail'' */ +} + +/* + * beginning of initialization; allocate space to store initialized data. + * remember storage class for writeout in endinit(). + * p is the newly declarated type. + */ +void +beginit(struct symtab *sp) +{ + struct initctx *ict; + struct instk *is = &pbase; + +#ifdef PCC_DEBUG + if (idebug) + printf("beginit(%p), sclass %s\n", sp, scnames(sp->sclass)); +#endif + + if (pstk) { +#ifdef PCC_DEBUG + if (idebug) + printf("beginit: saving ctx pstk %p\n", pstk); +#endif + /* save old context */ + ict = tmpalloc(sizeof(struct initctx)); + ict->prev = inilnk; + inilnk = ict; + ict->pstk = pstk; + ict->psym = csym; + ict->lpole = lpole; + ict->basesz = basesz; + ict->numents = numents; + is = tmpalloc(sizeof(struct instk)); + } + csym = sp; + + numents = 0; /* no entries in array list */ + if (ISARY(sp->stype)) { + basesz = tsize(DECREF(sp->stype), sp->sdf+1, sp->sap); + if (basesz == 0) { + uerror("array has incomplete type"); + basesz = SZINT; + } + } else + basesz = tsize(DECREF(sp->stype), sp->sdf, sp->sap); + SLIST_INIT(&lpole); + + /* first element */ + if (ISSOU(sp->stype)) { + is->in_lnk = strmemb(sp->sap); + } else + is->in_lnk = NULL; + is->in_n = 0; + is->in_t = sp->stype; + is->in_sym = sp; + is->in_df = sp->sdf; + is->in_fl = 0; + is->in_prev = NULL; + pstk = is; +} + +/* + * Push a new entry on the initializer stack. + * The new entry will be "decremented" to the new sub-type of the previous + * entry when called. + * Popping of entries is done elsewhere. + */ +static void +stkpush(void) +{ + struct instk *is; + struct symtab *sq, *sp; + TWORD t; + + if (pstk == NULL) { + sp = csym; + t = 0; + } else { + t = pstk->in_t; + sp = pstk->in_sym; + } + +#ifdef PCC_DEBUG + if (idebug) { + printf("stkpush: '%s' %s ", sp->sname, scnames(sp->sclass)); + tprint(stdout, t, 0); + } +#endif + + /* + * Figure out what the next initializer will be, and push it on + * the stack. If this is an array, just decrement type, if it + * is a struct or union, extract the next element. + */ + is = tmpalloc(sizeof(struct instk)); + is->in_fl = 0; + is->in_n = 0; + if (pstk == NULL) { + /* stack empty */ + is->in_lnk = ISSOU(sp->stype) ? strmemb(sp->sap) : NULL; + is->in_t = sp->stype; + is->in_sym = sp; + is->in_df = sp->sdf; + } else if (ISSOU(t)) { + sq = pstk->in_lnk; + if (sq == NULL) { + uerror("excess of initializing elements"); + } else { + is->in_lnk = ISSOU(sq->stype) ? strmemb(sq->sap) : NULL; + is->in_t = sq->stype; + is->in_sym = sq; + is->in_df = sq->sdf; + } + } else if (ISARY(t)) { + is->in_lnk = ISSOU(DECREF(t)) ? strmemb(pstk->in_sym->sap) : 0; + is->in_t = DECREF(t); + is->in_sym = sp; + if (pstk->in_df->ddim != NOOFFSET && pstk->in_df->ddim && + pstk->in_n >= pstk->in_df->ddim) { + werror("excess of initializing elements"); + pstk->in_n--; + } + is->in_df = pstk->in_df+1; + } else + uerror("too many left braces"); + is->in_prev = pstk; + pstk = is; + +#ifdef PCC_DEBUG + if (idebug) { + printf(" newtype "); + tprint(stdout, is->in_t, 0); + printf("\n"); + } +#endif +} + +/* + * pop down to either next level that can handle a new initializer or + * to the next braced level. + */ +static void +stkpop(void) +{ +#ifdef PCC_DEBUG + if (idebug) + printf("stkpop\n"); +#endif + for (; pstk; pstk = pstk->in_prev) { + if (pstk->in_t == STRTY && pstk->in_lnk != NULL) { + pstk->in_lnk = pstk->in_lnk->snext; + if (pstk->in_lnk != NULL) + break; + } + if (ISSOU(pstk->in_t) && pstk->in_fl) + break; /* need } */ + if (ISARY(pstk->in_t)) { + pstk->in_n++; + if (pstk->in_fl) + break; + if (pstk->in_df->ddim == NOOFFSET || + pstk->in_n < pstk->in_df->ddim) + break; /* ger more elements */ + } + } +#ifdef PCC_DEBUG + if (idebug > 1) + prtstk(pstk); +#endif +} + +/* + * Count how many elements an array may consist of. + */ +static int +acalc(struct instk *is, int n) +{ + if (is == NULL || !ISARY(is->in_t)) + return 0; + return acalc(is->in_prev, n * is->in_df->ddim) + n * is->in_n; +} + +/* + * Find current bit offset of the top element on the stack from + * the beginning of the aggregate. + */ +static CONSZ +findoff(void) +{ + struct instk *is; + OFFSZ off; + +#ifdef PCC_DEBUG + if (ISARY(pstk->in_t)) + cerror("findoff on bad type %x", pstk->in_t); +#endif + + /* + * Offset calculations. If: + * - previous type is STRTY, soffset has in-struct offset. + * - this type is ARY, offset is ninit*stsize. + */ + for (off = 0, is = pstk; is; is = is->in_prev) { + if (is->in_prev && is->in_prev->in_t == STRTY) + off += is->in_sym->soffset; + if (ISARY(is->in_t)) { + /* suesize is the basic type, so adjust */ + TWORD t = is->in_t; + OFFSZ o; + while (ISARY(t)) + t = DECREF(t); + if (ISPTR(t)) { + o = SZPOINT(t); /* XXX use tsize() */ + } else { + o = tsize(t, is->in_sym->sdf, is->in_sym->sap); + } + off += o * acalc(is, 1); + while (is->in_prev && ISARY(is->in_prev->in_t)) { + if (is->in_prev->in_prev && + is->in_prev->in_prev->in_t == STRTY) + off += is->in_sym->soffset; + is = is->in_prev; + } + } + } +#ifdef PCC_DEBUG + if (idebug>1) { + printf("findoff: off %lld\n", off); + prtstk(pstk); + } +#endif + return off; +} + +/* + * Insert the node p with size fsz at position off. + * Bit fields are already dealt with, so a node of correct type + * with correct alignment and correct bit offset is given. + */ +static void +nsetval(CONSZ off, int fsz, NODE *p) +{ + struct llist *ll; + struct ilist *il; + + if (idebug>1) + printf("setval: off %lld fsz %d p %p\n", off, fsz, p); + + if (fsz == 0) + return; + + ll = setll(off); + off -= ll->begsz; + if (ll->il == NULL) { + ll->il = getil(NULL, off, fsz, p); + } else { + il = ll->il; + if (il->off > off) { + ll->il = getil(ll->il, off, fsz, p); + } else { + for (il = ll->il; il->next; il = il->next) + if (il->off <= off && il->next->off > off) + break; + if (il->off == off) { + /* replace */ + nfree(il->n); + il->n = p; + } else + il->next = getil(il->next, off, fsz, p); + } + } +} + +/* + * take care of generating a value for the initializer p + * inoff has the current offset (last bit written) + * in the current word being generated + * Returns the offset. + */ +CONSZ +scalinit(NODE *p) +{ + CONSZ woff; + NODE *q; + int fsz; + +#ifdef PCC_DEBUG + if (idebug > 2) { + printf("scalinit(%p)\n", p); + fwalk(p, eprint, 0); + prtstk(pstk); + } +#endif + + if (nerrors) + return 0; + + p = optim(p); + +#ifdef notdef /* leave to the target to decide if useable */ + if (csym->sclass != AUTO && p->n_op != ICON && + p->n_op != FCON && p->n_op != NAME) + cerror("scalinit not leaf"); +#endif + + /* Out of elements? */ + if (pstk == NULL) { + uerror("excess of initializing elements"); + return 0; + } + + /* + * Get to the simple type if needed. + */ + while (ISSOU(pstk->in_t) || ISARY(pstk->in_t)) { + stkpush(); + /* If we are doing auto struct init */ + if (ISSOU(pstk->in_t) && ISSOU(p->n_type) && + suemeq(pstk->in_sym->sap, p->n_ap)) + break; + } + + if (ISSOU(pstk->in_t) == 0) { + /* let buildtree do typechecking (and casting) */ + q = block(NAME, NIL,NIL, pstk->in_t, pstk->in_df, + pstk->in_sym->sap); + p = buildtree(ASSIGN, q, p); + nfree(p->n_left); + q = optim(p->n_right); + nfree(p); + } else + q = p; + + woff = findoff(); + + /* bitfield sizes are special */ + if (pstk->in_sym->sclass & FIELD) + fsz = -(pstk->in_sym->sclass & FLDSIZ); + else + fsz = (int)tsize(pstk->in_t, pstk->in_sym->sdf, + pstk->in_sym->sap); + + nsetval(woff, fsz, q); + + stkpop(); +#ifdef PCC_DEBUG + if (idebug > 2) { + printf("scalinit e(%p)\n", q); + } +#endif + return woff; +} + +/* + * Generate code to insert a value into a bitfield. + */ +static void +insbf(OFFSZ off, int fsz, int val) +{ + struct symtab sym; + NODE *p, *r; + TWORD typ; + +#ifdef PCC_DEBUG + if (idebug > 1) + printf("insbf: off %lld fsz %d val %d\n", off, fsz, val); +#endif + + if (fsz == 0) + return; + + /* small opt: do char instead of bf asg */ + if ((off & (ALCHAR-1)) == 0 && fsz == SZCHAR) + typ = CHAR; + else + typ = INT; + /* Fake a struct reference */ + p = buildtree(ADDROF, nametree(csym), NIL); + sym.stype = typ; + sym.squal = 0; + sym.sdf = 0; + sym.sap = MKAP(typ); + sym.soffset = (int)off; + sym.sclass = (char)(typ == INT ? FIELD | fsz : MOU); + r = xbcon(0, &sym, typ); + p = block(STREF, p, r, INT, 0, MKAP(INT)); + ecode(buildtree(ASSIGN, stref(p), bcon(val))); +} + +/* + * Clear a bitfield, starting at off and size fsz. + */ +static void +clearbf(OFFSZ off, OFFSZ fsz) +{ + /* Pad up to the next even initializer */ + if ((off & (ALCHAR-1)) || (fsz < SZCHAR)) { + int ba = (int)(((off + (SZCHAR-1)) & ~(SZCHAR-1)) - off); + if (ba > fsz) + ba = (int)fsz; + insbf(off, ba, 0); + off += ba; + fsz -= ba; + } + while (fsz >= SZCHAR) { + insbf(off, SZCHAR, 0); + off += SZCHAR; + fsz -= SZCHAR; + } + if (fsz) + insbf(off, fsz, 0); +} + +/* + * final step of initialization. + * print out init nodes and generate copy code (if needed). + */ +void +endinit(void) +{ + struct llist *ll; + struct ilist *il; + int fsz; + OFFSZ lastoff, tbit; + +#ifdef PCC_DEBUG + if (idebug) + printf("endinit()\n"); +#endif + + if (csym->sclass != AUTO) + defloc(csym); + + /* Calculate total block size */ + if (ISARY(csym->stype) && csym->sdf->ddim == NOOFFSET) { + tbit = numents*basesz; /* open-ended arrays */ + csym->sdf->ddim = numents; + if (csym->sclass == AUTO) { /* Get stack space */ + csym->soffset = NOOFFSET; + oalloc(csym, &autooff); + } + } else + tbit = tsize(csym->stype, csym->sdf, csym->sap); + + /* Traverse all entries and print'em out */ + lastoff = 0; + SLIST_FOREACH(ll, &lpole, next) { + for (il = ll->il; il; il = il->next) { +#ifdef PCC_DEBUG + if (idebug > 1) { + printf("off %lld size %d val %lld type ", + ll->begsz+il->off, il->fsz, il->n->n_lval); + tprint(stdout, il->n->n_type, 0); + printf("\n"); + } +#endif + fsz = il->fsz; + if (csym->sclass == AUTO) { + struct symtab sym; + NODE *p, *r, *n; + + if (ll->begsz + il->off > lastoff) + clearbf(lastoff, + (ll->begsz + il->off) - lastoff); + + /* Fake a struct reference */ + p = buildtree(ADDROF, nametree(csym), NIL); + n = il->n; + sym.stype = n->n_type; + sym.squal = n->n_qual; + sym.sdf = n->n_df; + sym.sap = n->n_ap; + sym.soffset = (int)(ll->begsz + il->off); + sym.sclass = (char)(fsz < 0 ? FIELD | -fsz : 0); + r = xbcon(0, &sym, INT); + p = block(STREF, p, r, INT, 0, MKAP(INT)); + ecomp(buildtree(ASSIGN, stref(p), il->n)); + if (fsz < 0) + fsz = -fsz; + + } else { + if (ll->begsz + il->off > lastoff) + zbits(lastoff, + (ll->begsz + il->off) - lastoff); + if (fsz < 0) { + fsz = -fsz; + infld(il->off, fsz, il->n->n_lval); + } else + ninval(il->off, fsz, il->n); + tfree(il->n); + } + lastoff = ll->begsz + il->off + fsz; + } + } + if (csym->sclass == AUTO) { + clearbf(lastoff, tbit-lastoff); + } else + zbits(lastoff, tbit-lastoff); + + endictx(); +} + +void +endictx(void) +{ + struct initctx *ict = inilnk; + + if (ict == NULL) + return; + + pstk = ict->pstk; + csym = ict->psym; + lpole = ict->lpole; + basesz = ict->basesz; + numents = ict->numents; + inilnk = inilnk->prev; +#ifdef PCC_DEBUG + if (idebug) + printf("endinit: restoring ctx pstk %p\n", pstk); +#endif +} + +/* + * process an initializer's left brace + */ +void +ilbrace() +{ + +#ifdef PCC_DEBUG + if (idebug) + printf("ilbrace()\n"); +#endif + + if (pstk == NULL) + return; + + stkpush(); + pstk->in_fl = 1; /* mark lbrace */ +#ifdef PCC_DEBUG + if (idebug > 1) + prtstk(pstk); +#endif +} + +/* + * called when a '}' is seen + */ +void +irbrace() +{ +#ifdef PCC_DEBUG + if (idebug) + printf("irbrace()\n"); + if (idebug > 2) + prtstk(pstk); +#endif + + if (pstk == NULL) + return; + + /* Got right brace, search for corresponding in the stack */ + for (; pstk->in_prev != NULL; pstk = pstk->in_prev) { + if(!pstk->in_fl) + continue; + + /* we have one now */ + + pstk->in_fl = 0; /* cancel { */ + if (ISARY(pstk->in_t)) + pstk->in_n = pstk->in_df->ddim; + else if (pstk->in_t == STRTY) { + while (pstk->in_lnk != NULL && + pstk->in_lnk->snext != NULL) + pstk->in_lnk = pstk->in_lnk->snext; + } + stkpop(); + return; + } +} + +/* + * Create a new init stack based on given elements. + */ +static void +mkstack(NODE *p) +{ + +#ifdef PCC_DEBUG + if (idebug) { + printf("mkstack: %p\n", p); + if (idebug > 1 && p) + fwalk(p, eprint, 0); + } +#endif + + if (p == NULL) + return; + mkstack(p->n_left); + + switch (p->n_op) { + case LB: /* Array index */ + if (p->n_right->n_op != ICON) + cerror("mkstack"); + if (!ISARY(pstk->in_t)) + uerror("array indexing non-array"); + pstk->in_n = (int)p->n_right->n_lval; + nfree(p->n_right); + break; + + case NAME: + if (pstk->in_lnk) { + for (; pstk->in_lnk; pstk->in_lnk = pstk->in_lnk->snext) + if (pstk->in_lnk->sname == (char *)p->n_sp) + break; + if (pstk->in_lnk == NULL) + uerror("member missing"); + } else { + uerror("not a struct/union"); + } + break; + default: + cerror("mkstack2"); + } + nfree(p); + stkpush(); + +} + +/* + * Initialize a specific element, as per C99. + */ +void +desinit(NODE *p) +{ + int op = p->n_op; + + if (pstk == NULL) + stkpush(); /* passed end of array */ + while (pstk->in_prev && pstk->in_fl == 0) + pstk = pstk->in_prev; /* Empty stack */ + + if (ISSOU(pstk->in_t)) + pstk->in_lnk = strmemb(pstk->in_sym->sap); + + mkstack(p); /* Setup for assignment */ + + /* pop one step if SOU, ilbrace will push */ + if (op == NAME || op == LB) + pstk = pstk->in_prev; + +#ifdef PCC_DEBUG + if (idebug > 1) { + printf("desinit e\n"); + prtstk(pstk); + } +#endif +} + +/* + * Convert a string to an array of char/wchar for asginit. + */ +static void +strcvt(NODE *p) +{ + NODE *q = p; + char *s; + int i; + +#ifdef mach_arm + /* XXX */ + if (p->n_op == UMUL && p->n_left->n_op == ADDROF) + p = p->n_left->n_left; +#endif + + for (s = p->n_sp->sname; *s != 0; ) { + if (*s++ == '\\') { + i = esccon(&s); + } else + i = (unsigned char)s[-1]; + asginit(bcon(i)); + } + tfree(q); +} + +/* + * Do an assignment to a struct element. + */ +void +asginit(NODE *p) +{ + int g; + +#ifdef PCC_DEBUG + if (idebug) + printf("asginit %p\n", p); + if (idebug > 1 && p) + fwalk(p, eprint, 0); +#endif + + /* convert string to array of char/wchar */ + if (p && (DEUNSIGN(p->n_type) == ARY+CHAR || + p->n_type == ARY+WCHAR_TYPE)) { + TWORD t; + + t = p->n_type == ARY+WCHAR_TYPE ? ARY+WCHAR_TYPE : ARY+CHAR; + /* + * ...but only if next element is ARY+CHAR, otherwise + * just fall through. + */ + + /* HACKHACKHACK */ + struct instk *is = pstk; + + if (pstk == NULL) + stkpush(); + while (ISSOU(pstk->in_t) || ISARY(pstk->in_t)) + stkpush(); + if (pstk->in_prev && + (DEUNSIGN(pstk->in_prev->in_t) == t || + pstk->in_prev->in_t == t)) { + pstk = pstk->in_prev; + if ((g = pstk->in_fl) == 0) + pstk->in_fl = 1; /* simulate ilbrace */ + + strcvt(p); + if (g == 0) + irbrace(); /* will fill with zeroes */ + return; + } else + pstk = is; /* no array of char */ + /* END HACKHACKHACK */ + } + + if (p == NULL) { /* only end of compound stmt */ + irbrace(); + } else /* assign next element */ + scalinit(p); +} + +#ifdef PCC_DEBUG +void +prtstk(struct instk *in) +{ + int i, o = 0; + + printf("init stack:\n"); + for (; in != NULL; in = in->in_prev) { + for (i = 0; i < o; i++) + printf(" "); + printf("%p) '%s' ", in, in->in_sym->sname); + tprint(stdout, in->in_t, 0); + printf(" %s ", scnames(in->in_sym->sclass)); + if (in->in_df /* && in->in_df->ddim */) + printf("arydim=%d ", in->in_df->ddim); + printf("ninit=%d ", in->in_n); + if (BTYPE(in->in_t) == STRTY || ISARY(in->in_t)) + printf("stsize=%d ", + (int)tsize(in->in_t, in->in_df, in->in_sym->sap)); + if (in->in_fl) printf("{ "); + printf("soff=%d ", in->in_sym->soffset); + if (in->in_t == STRTY) { + if (in->in_lnk) + printf("curel %s ", in->in_lnk->sname); + else + printf("END struct"); + } + printf("\n"); + o++; + } +} +#endif + +/* + * Do a simple initialization. + * At block 0, just print out the value, at higher levels generate + * appropriate code. + */ +void +simpleinit(struct symtab *sp, NODE *p) +{ + NODE *q, *r, *nt; + TWORD t; + int sz; + + /* May be an initialization of an array of char by a string */ + if ((DEUNSIGN(p->n_type) == ARY+CHAR && + DEUNSIGN(sp->stype) == ARY+CHAR) || + (DEUNSIGN(p->n_type) == DEUNSIGN(ARY+WCHAR_TYPE) && + DEUNSIGN(sp->stype) == DEUNSIGN(ARY+WCHAR_TYPE))) { + /* Handle "aaa" as { 'a', 'a', 'a' } */ + beginit(sp); + strcvt(p); + if (csym->sdf->ddim == NOOFFSET) + scalinit(bcon(0)); /* Null-term arrays */ + endinit(); + return; + } + + nt = nametree(sp); + switch (sp->sclass) { + case STATIC: + case EXTDEF: + q = nt; +#ifndef NO_COMPLEX + if (ANYCX(q) || ANYCX(p)) { + r = cxop(ASSIGN, q, p); + /* XXX must unwind the code generated here */ + /* We can rely on correct code generated */ + p = r->n_left->n_right->n_left; + r->n_left->n_right->n_left = bcon(0); + tfree(r); + defloc(sp); + r = p->n_left->n_right; + sz = (int)tsize(r->n_type, r->n_df, r->n_ap); + ninval(0, sz, r); + ninval(0, sz, p->n_right->n_right); + tfree(p); + break; + } +#endif + p = optim(buildtree(ASSIGN, nt, p)); + defloc(sp); + q = p->n_right; + t = q->n_type; + sz = (int)tsize(t, q->n_df, q->n_ap); + ninval(0, sz, q); + tfree(p); + break; + + case AUTO: + case REGISTER: + if (ISARY(sp->stype)) + cerror("no array init"); + q = nt; +#ifndef NO_COMPLEX + + if (ANYCX(q) || ANYCX(p)) + r = cxop(ASSIGN, q, p); + else +#endif + r = buildtree(ASSIGN, q, p); + ecomp(r); + break; + + default: + uerror("illegal initialization"); + } +} diff --git a/compilers/pcc/pcc-1.0.0/cc/ccom/inline.c b/compilers/pcc/pcc-1.0.0/cc/ccom/inline.c new file mode 100644 index 00000000..908c429b --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/ccom/inline.c @@ -0,0 +1,538 @@ +/* $Id: inline.c,v 1.37.2.2 2011/02/26 11:31:45 ragge Exp $ */ +/* + * Copyright (c) 2003, 2008 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "pass1.h" + +#include + +/* + * Simple description of how the inlining works: + * A function found with the keyword "inline" is always saved. + * If it also has the keyword "extern" it is written out thereafter. + * If it has the keyword "static" it will be written out if it is referenced. + * inlining will only be done if -xinline is given, and only if it is + * possible to inline the function. + */ +static void printip(struct interpass *pole); + +struct ntds { + int temp; + TWORD type; + union dimfun *df; + struct attr *attr; +}; + +/* + * ilink from ipole points to the next struct in the list of functions. + */ +static struct istat { + SLIST_ENTRY(istat) link; + struct symtab *sp; + int flags; +#define CANINL 1 /* function is possible to inline */ +#define WRITTEN 2 /* function is written out */ +#define REFD 4 /* Referenced but not yet written out */ + struct ntds *nt;/* Array of arg temp type data */ + int nargs; /* number of args in array */ + int retval; /* number of return temporary, if any */ + struct interpass shead; +} *cifun; + +static SLIST_HEAD(, istat) ipole = { NULL, &ipole.q_forw }; +static int nlabs; + +#define IP_REF (MAXIP+1) +#ifdef PCC_DEBUG +#define SDEBUG(x) if (sdebug) printf x +#else +#define SDEBUG(x) +#endif + +int isinlining; +int inlnodecnt, inlstatcnt; + +#define SZSI sizeof(struct istat) +#define ialloc() memset(permalloc(SZSI), 0, SZSI); inlstatcnt++ + +static void +tcnt(NODE *p, void *arg) +{ + inlnodecnt++; + if (nlabs > 1 && (p->n_op == REG || p->n_op == OREG) && + regno(p) == FPREG) + SLIST_FIRST(&ipole)->flags &= ~CANINL; /* no stack refs */ + if (p->n_op == NAME || p->n_op == ICON) + p->n_sp = NULL; /* let symtabs be freed for inline funcs */ + if (nflag) + printf("locking node %p\n", p); +} + +static struct istat * +findfun(struct symtab *sp) +{ + struct istat *is; + + SLIST_FOREACH(is, &ipole, link) + if (is->sp == sp) + return is; + return NULL; +} + +static void +refnode(struct symtab *sp) +{ + struct interpass *ip; + + SDEBUG(("refnode(%s)\n", sp->sname)); + + ip = permalloc(sizeof(*ip)); + ip->type = IP_REF; + ip->ip_name = (char *)sp; + inline_addarg(ip); +} + +void +inline_addarg(struct interpass *ip) +{ + extern NODE *cftnod; + + SDEBUG(("inline_addarg(%p)\n", ip)); + DLIST_INSERT_BEFORE(&cifun->shead, ip, qelem); + if (ip->type == IP_DEFLAB) + nlabs++; + if (ip->type == IP_NODE) + walkf(ip->ip_node, tcnt, 0); /* Count as saved */ + if (cftnod) + cifun->retval = regno(cftnod); +} + +/* + * Called to setup for inlining of a new function. + */ +void +inline_start(struct symtab *sp) +{ + struct istat *is; + + SDEBUG(("inline_start(\"%s\")\n", sp->sname)); + + if (isinlining) + cerror("already inlining function"); + + if ((is = findfun(sp)) != 0) { + if (!DLIST_ISEMPTY(&is->shead, qelem)) + uerror("inline function already defined"); + } else { + is = ialloc(); + is->sp = sp; + SLIST_INSERT_FIRST(&ipole, is, link); + DLIST_INIT(&is->shead, qelem); + } + cifun = is; + nlabs = 0; + isinlining++; +} + +/* + * End of an inline function. In C99 an inline function declared "extern" + * should also have external linkage and are therefore printed out. + * But; this is the opposite for gcc inline functions, hence special + * care must be taken to handle that specific case. + */ +void +inline_end() +{ + + SDEBUG(("inline_end()\n")); + + if (sdebug)printip(&cifun->shead); + isinlining = 0; + + if (attr_find(cifun->sp->sap, GCC_ATYP_GNU_INLINE)) { + if (cifun->sp->sclass == EXTDEF) + cifun->sp->sclass = 0; + else + cifun->sp->sclass = EXTDEF; + } + + if (cifun->sp->sclass == EXTDEF) { + cifun->flags |= REFD; + inline_prtout(); + } +} + +/* + * Called when an inline function is found, to be sure that it will + * be written out. + * The function may not be defined when inline_ref() is called. + */ +void +inline_ref(struct symtab *sp) +{ + struct istat *w; + + SDEBUG(("inline_ref(\"%s\")\n", sp->sname)); + if (sp->sclass == SNULL) + return; /* only inline, no references */ + if (isinlining) { + refnode(sp); + } else { + SLIST_FOREACH(w,&ipole, link) { + if (w->sp != sp) + continue; + w->flags |= REFD; + return; + } + /* function not yet defined, print out when found */ + w = ialloc(); + w->sp = sp; + w->flags |= REFD; + SLIST_INSERT_FIRST(&ipole, w, link); + DLIST_INIT(&w->shead, qelem); + } +} + +static void +puto(struct istat *w) +{ + struct interpass_prolog *ipp, *epp, *pp; + struct interpass *ip, *nip; + extern int crslab; + int lbloff = 0; + + /* Copy the saved function and print it out */ + ipp = 0; /* XXX data flow analysis */ + DLIST_FOREACH(ip, &w->shead, qelem) { + switch (ip->type) { + case IP_EPILOG: + case IP_PROLOG: + if (ip->type == IP_PROLOG) { + ipp = (struct interpass_prolog *)ip; + /* fix label offsets */ + lbloff = crslab - ipp->ip_lblnum; + } else { + epp = (struct interpass_prolog *)ip; + crslab += (epp->ip_lblnum - ipp->ip_lblnum); + } + pp = tmpalloc(sizeof(struct interpass_prolog)); + memcpy(pp, ip, sizeof(struct interpass_prolog)); + pp->ip_lblnum += lbloff; +#ifdef PCC_DEBUG + if (ip->type == IP_EPILOG && crslab != pp->ip_lblnum) + cerror("puto: %d != %d", crslab, pp->ip_lblnum); +#endif + pass2_compile((struct interpass *)pp); + break; + + case IP_REF: + inline_ref((struct symtab *)ip->ip_name); + break; + + default: + nip = tmpalloc(sizeof(struct interpass)); + *nip = *ip; + if (nip->type == IP_NODE) { + NODE *p; + + p = nip->ip_node = ccopy(nip->ip_node); + if (p->n_op == GOTO) + p->n_left->n_lval += lbloff; + else if (p->n_op == CBRANCH) + p->n_right->n_lval += lbloff; + } else if (nip->type == IP_DEFLAB) + nip->ip_lbl += lbloff; + pass2_compile(nip); + break; + } + } + w->flags |= WRITTEN; +} + +/* + * printout functions that are referenced. + */ +void +inline_prtout() +{ + struct istat *w; + int gotone = 0; + + SLIST_FOREACH(w, &ipole, link) { + if ((w->flags & (REFD|WRITTEN)) == REFD && + !DLIST_ISEMPTY(&w->shead, qelem)) { + defloc(w->sp); + puto(w); + w->flags |= WRITTEN; + gotone++; + } + } + if (gotone) + inline_prtout(); +} + +#if 1 +static void +printip(struct interpass *pole) +{ + static char *foo[] = { + 0, "NODE", "PROLOG", "STKOFF", "EPILOG", "DEFLAB", "DEFNAM", "ASM" }; + struct interpass *ip; + struct interpass_prolog *ipplg, *epplg; + + DLIST_FOREACH(ip, pole, qelem) { + if (ip->type > MAXIP) + printf("IP(%d) (%p): ", ip->type, ip); + else + printf("%s (%p): ", foo[ip->type], ip); + switch (ip->type) { + case IP_NODE: printf("\n"); +#ifdef PCC_DEBUG + fwalk(ip->ip_node, eprint, 0); break; +#endif + case IP_PROLOG: + ipplg = (struct interpass_prolog *)ip; + printf("%s %s regs %lx autos %d mintemp %d minlbl %d\n", + ipplg->ipp_name, ipplg->ipp_vis ? "(local)" : "", + (long)ipplg->ipp_regs[0], ipplg->ipp_autos, + ipplg->ip_tmpnum, ipplg->ip_lblnum); + break; + case IP_EPILOG: + epplg = (struct interpass_prolog *)ip; + printf("%s %s regs %lx autos %d mintemp %d minlbl %d\n", + epplg->ipp_name, epplg->ipp_vis ? "(local)" : "", + (long)epplg->ipp_regs[0], epplg->ipp_autos, + epplg->ip_tmpnum, epplg->ip_lblnum); + break; + case IP_DEFLAB: printf(LABFMT "\n", ip->ip_lbl); break; + case IP_DEFNAM: printf("\n"); break; + case IP_ASM: printf("%s\n", ip->ip_asm); break; + default: + break; + } + } +} +#endif + +static int toff; + +static NODE * +mnode(struct ntds *nt, NODE *p) +{ + NODE *q; + int num = nt->temp + toff; + + if (p->n_op == CM) { + q = p->n_right; + q = tempnode(num, nt->type, nt->df, nt->attr); + nt--; + p->n_right = buildtree(ASSIGN, q, p->n_right); + p->n_left = mnode(nt, p->n_left); + p->n_op = COMOP; + } else { + p = pconvert(p); + q = tempnode(num, nt->type, nt->df, nt->attr); + p = buildtree(ASSIGN, q, p); + } + return p; +} + +static void +rtmps(NODE *p, void *arg) +{ + if (p->n_op == TEMP) + regno(p) += toff; +} + +/* + * Inline a function. Returns the return value. + * There are two major things that must be converted when + * inlining a function: + * - Label numbers must be updated with an offset. + * - The stack block must be relocated (add to REG or OREG). + * - Temporaries should be updated (but no must) + */ +NODE * +inlinetree(struct symtab *sp, NODE *f, NODE *ap) +{ + extern int crslab, tvaloff; + struct istat *is = findfun(sp); + struct interpass *ip, *ipf, *ipl; + int lmin, stksz, l0, l1, l2, gainl; + OFFSZ stkoff; + NODE *p, *rp; + + if (is == NULL || nerrors) { + inline_ref(sp); /* prototype of not yet declared inline ftn */ + return NIL; + } + + SDEBUG(("inlinetree(%p,%p) OK %d\n", f, ap, is->flags & CANINL)); + + gainl = attr_find(sp->sap, GCC_ATYP_ALW_INL) != NULL; + + if ((is->flags & CANINL) == 0 && gainl) + werror("cannot inline but always_inline"); + + if ((is->flags & CANINL) == 0 || (xinline == 0 && gainl == 0)) { + if (is->sp->sclass == STATIC || is->sp->sclass == USTATIC) + inline_ref(sp); + return NIL; + } + + if (isinlining && cifun->sp == sp) { + /* Do not try to inline ourselves */ + inline_ref(sp); + return NIL; + } + +#ifdef mach_i386 + if (kflag) { + is->flags |= REFD; /* if static inline, emit */ + return NIL; /* XXX cannot handle hidden ebx arg */ + } +#endif + + stkoff = stksz = 0; + /* emit jumps to surround inline function */ + branch(l0 = getlab()); + plabel(l1 = getlab()); + l2 = getlab(); + SDEBUG(("branch labels %d,%d,%d\n", l0, l1, l2)); + + ipf = DLIST_NEXT(&is->shead, qelem); /* prolog */ + ipl = DLIST_PREV(&is->shead, qelem); /* epilog */ + + /* Fix label & temp offsets */ +#define IPP(x) ((struct interpass_prolog *)x) + SDEBUG(("pre-offsets crslab %d tvaloff %d\n", crslab, tvaloff)); + lmin = crslab - IPP(ipf)->ip_lblnum; + crslab += (IPP(ipl)->ip_lblnum - IPP(ipf)->ip_lblnum) + 1; + toff = tvaloff - IPP(ipf)->ip_tmpnum; + tvaloff += (IPP(ipl)->ip_tmpnum - IPP(ipf)->ip_tmpnum) + 1; + SDEBUG(("offsets crslab %d lmin %d tvaloff %d toff %d\n", + crslab, lmin, tvaloff, toff)); + + /* traverse until first real label */ + ipf = DLIST_NEXT(ipf, qelem); + do + ipf = DLIST_NEXT(ipf, qelem); + while (ipf->type != IP_DEFLAB); + + /* traverse backwards to last label */ + do + ipl = DLIST_PREV(ipl, qelem); + while (ipl->type != IP_DEFLAB); + + /* So, walk over all statements and emit them */ + for (ip = ipf; ip != ipl; ip = DLIST_NEXT(ip, qelem)) { + switch (ip->type) { + case IP_NODE: + p = ccopy(ip->ip_node); + if (p->n_op == GOTO) + p->n_left->n_lval += lmin; + else if (p->n_op == CBRANCH) + p->n_right->n_lval += lmin; + walkf(p, rtmps, 0); +#ifdef PCC_DEBUG + if (sdebug) { + printf("converted node\n"); + fwalk(ip->ip_node, eprint, 0); + fwalk(p, eprint, 0); + } +#endif + send_passt(IP_NODE, p); + break; + + case IP_DEFLAB: + SDEBUG(("converted label %d to %d\n", + ip->ip_lbl, ip->ip_lbl + lmin)); + send_passt(IP_DEFLAB, ip->ip_lbl + lmin); + break; + + case IP_ASM: + send_passt(IP_ASM, ip->ip_asm); + break; + + case IP_REF: + inline_ref((struct symtab *)ip->ip_name); + break; + + default: + cerror("bad inline stmt %d", ip->type); + } + } + SDEBUG(("last label %d to %d\n", ip->ip_lbl, ip->ip_lbl + lmin)); + send_passt(IP_DEFLAB, ip->ip_lbl + lmin); + + branch(l2); + plabel(l0); + + rp = block(GOTO, bcon(l1), NIL, INT, 0, MKAP(INT)); + if (is->retval) + p = tempnode(is->retval + toff, DECREF(sp->stype), + sp->sdf, sp->sap); + else + p = bcon(0); + rp = buildtree(COMOP, rp, p); + + if (is->nargs) { + p = mnode(&is->nt[is->nargs-1], ap); + rp = buildtree(COMOP, p, rp); + } + + tfree(f); + return rp; +} + +void +inline_args(struct symtab **sp, int nargs) +{ + struct istat *cf; + int i; + + SDEBUG(("inline_args\n")); + cf = cifun; + /* + * First handle arguments. We currently do not inline anything if: + * - function has varargs + * - function args are volatile, checked if no temp node is asg'd. + */ + if (nargs) { + for (i = 0; i < nargs; i++) + if ((sp[i]->sflags & STNODE) == 0) + return; /* not temporary */ + cf->nt = permalloc(sizeof(struct ntds)*nargs); + for (i = 0; i < nargs; i++) { + cf->nt[i].temp = sp[i]->soffset; + cf->nt[i].type = sp[i]->stype; + cf->nt[i].df = sp[i]->sdf; + cf->nt[i].attr = sp[i]->sap; + } + } + cf->nargs = nargs; + cf->flags |= CANINL; +} diff --git a/compilers/pcc/pcc-1.0.0/cc/ccom/main.c b/compilers/pcc/pcc-1.0.0/cc/ccom/main.c new file mode 100644 index 00000000..a66982c8 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/ccom/main.c @@ -0,0 +1,397 @@ +/* $Id: main.c,v 1.106 2011/01/22 22:08:23 ragge Exp $ */ + +/* + * Copyright (c) 2002 Anders Magnusson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include + +#include "pass1.h" +#include "pass2.h" + +int sflag, nflag, oflag, kflag, pflag; +int lflag, odebug, rdebug, s2debug, udebug, x2debug; +#if !defined(MULTIPASS) || defined(PASST) +int iTflag, oTflag; +#endif +int xdebug, sdebug, gflag, c2debug, pdebug, g2debug; +#ifdef CHAR_UNSIGNED +int funsigned_char = 1; +#else +int funsigned_char = 0; +#endif +int sspflag; +int xssaflag, xtailcallflag, xtemps, xdeljumps, xdce, xinline, xccp; + +int e2debug, t2debug, f2debug, b2debug; + +/* + * Ensure that this struct matches defines in manifest.h! + */ +const struct attr2 btattr[32] = { +#define BTA(x) { 0, ATTR_BASETYP, { { SZ##x }, { AL##x }, }, }, + { 0 }, /* UNDEF */ + { 0 }, /* FARG */ + BTA(CHAR) + BTA(CHAR) + BTA(SHORT) + BTA(SHORT) + BTA(INT) + BTA(INT) + BTA(LONG) + BTA(LONG) + BTA(LONGLONG) + BTA(LONGLONG) + BTA(FLOAT) + BTA(DOUBLE) + BTA(LDOUBLE) + { 0 }, /* STRTY */ + { 0 }, /* UNIONTY */ + { 0 }, /* unused */ + { 0 }, /* unused */ + { 0, ATTR_BASETYP }, /* VOID */ + { 0 }, /* SIGNED */ + BTA(BOOL) + BTA(FLOAT) /* FIMAG */ + BTA(DOUBLE) /* IMAG */ + BTA(LDOUBLE) /* LIMAG */ + BTA(FLOAT) /* FCOMPLEX */ + BTA(DOUBLE) /* COMPLEX */ + BTA(LDOUBLE) /* LCOMPLEX */ +}; + +char *prgname; + +static void prtstats(void); + +static void +usage(void) +{ + (void)fprintf(stderr, "usage: %s [option] [infile] [outfile]...\n", + prgname); + exit(1); +} + +static void +segvcatch(int a) +{ + char buf[1024]; + int dummy; + + snprintf(buf, sizeof buf, "%sinternal compiler error: %s, line %d\n", + nerrors ? "" : "major ", ftitle, lineno); + dummy = write(STDERR_FILENO, buf, strlen(buf)); + _exit(1); +} + +static void +fflags(char *str) +{ + int flagval = 1; + + if (strncmp("no-", str, 3) == 0) { + str += 3; + flagval = 0; + } + + if (strcmp(str, "signed-char") == 0) + funsigned_char = !flagval; + else if (strcmp(str, "unsigned-char") == 0) + funsigned_char = flagval; + else if (strcmp(str, "stack-protector") == 0) + sspflag = flagval; + else if (strcmp(str, "stack-protector-all") == 0) + sspflag = flagval; + else if (strncmp(str, "pack-struct", 11) == 0) + pragma_allpacked = (strlen(str) > 12 ? atoi(str+12) : 1); + else { + fprintf(stderr, "unrecognised option '%s'\n", str); + usage(); + } +} + +/* control multiple files */ +int +main(int argc, char *argv[]) +{ + + int ch; + +#ifdef TIMING + struct timeval t1, t2; + + (void)gettimeofday(&t1, NULL); +#endif + + prgname = argv[0]; + + while ((ch = getopt(argc, argv, "OT:VW:X:Z:f:gklm:psvwx:")) != -1) + switch (ch) { +#if !defined(MULTIPASS) || defined(PASS1) + case 'X': + while (*optarg) + switch (*optarg++) { + case 'd': ++ddebug; break; /* declarations */ + case 'i': ++idebug; break; /* initializations */ + case 'b': ++bdebug; break; /* buildtree */ + case 't': ++tdebug; break; /* type match */ + case 'e': ++edebug; break; /* pass1 exit */ + case 'x': ++xdebug; break; /* MD code */ + case 's': ++sdebug; break; /* inline */ + case 'n': ++nflag; break; /* node alloc */ + case 'o': ++oflag; break; /* optim */ + case 'p': ++pdebug; break; /* prototype */ + default: + fprintf(stderr, "unknown X flag '%c'\n", + optarg[-1]); + exit(1); + } +#endif + break; +#if !defined(MULTIPASS) || defined(PASST) + case 'T': + while (*optarg) + switch (*optarg++) { + case 'i': ++iTflag; break; + case 'o': ++oTflag; break; + case 'n': ++nflag; break; + default: + fprintf(stderr, "unknown T flag '%c'\n", + optarg[-1]); + exit(1); + } +#endif + break; +#if !defined(MULTIPASS) || defined(PASS2) + case 'Z': + while (*optarg) + switch (*optarg++) { + case 'f': /* instruction matching */ + ++f2debug; + break; + case 'e': /* print tree upon pass2 enter */ + ++e2debug; + break; + case 'o': ++odebug; break; + case 'r': /* register alloc/graph coloring */ + ++rdebug; + break; + case 'b': /* basic block and SSA building */ + ++b2debug; + break; + case 'c': /* code printout */ + ++c2debug; + break; + case 't': ++t2debug; break; + case 's': /* shape matching */ + ++s2debug; + break; + case 'u': /* Sethi-Ullman debugging */ + ++udebug; + break; + case 'x': ++x2debug; break; + case 'g': /* print flow graphs */ + ++g2debug; + break; + case 'n': ++nflag; break; + default: + fprintf(stderr, "unknown Z flag '%c'\n", + optarg[-1]); + exit(1); + } +#endif + break; + + case 'f': /* Language */ + fflags(optarg); + break; + + case 'g': /* Debugging */ + gflag = 1; + break; + + case 'k': /* PIC code */ + ++kflag; + break; + + case 'l': /* Linenos */ + ++lflag; + break; + + case 'm': /* Target-specific */ + mflags(optarg); + break; + + case 'p': /* Profiling */ + pflag = 1; + break; + + case 's': /* Statistics */ + ++sflag; + break; + + case 'W': /* Enable different warnings */ + Wflags(optarg); + break; + + case 'x': /* Different optimizations */ + if (strcmp(optarg, "ssa") == 0) + xssaflag++; + else if (strcmp(optarg, "tailcall") == 0) + xtailcallflag++; + else if (strcmp(optarg, "temps") == 0) + xtemps++; + else if (strcmp(optarg, "deljumps") == 0) + xdeljumps++; + else if (strcmp(optarg, "dce") == 0) + xdce++; + else if (strcmp(optarg, "inline") == 0) + xinline++; + else if (strcmp(optarg, "ccp") == 0) + xccp++; + else + usage(); + break; + case 'v': + printf("ccom: %s\n", VERSSTR); + break; + + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + if (argc > 0 && strcmp(argv[0], "-") != 0) { + if (freopen(argv[0], "r", stdin) == NULL) { + fprintf(stderr, "open input file '%s':", + argv[0]); + perror(NULL); + exit(1); + } + } + if (argc > 1 && strcmp(argv[1], "-") != 0) { + if (freopen(argv[1], "w", stdout) == NULL) { + fprintf(stderr, "open output file '%s':", + argv[1]); + perror(NULL); + exit(1); + } + } + + mkdope(); + signal(SIGSEGV, segvcatch); +#ifdef SIGBUS + signal(SIGBUS, segvcatch); +#endif + fregs = FREGS; /* number of free registers */ + lineno = 1; +#ifdef GCC_COMPAT + gcc_init(); +#endif + + /* starts past any of the above */ + reached = 1; + + bjobcode(); +#ifndef TARGET_VALIST + { + NODE *p = block(NAME, NIL, NIL, PTR|CHAR, NULL, MKAP(CHAR)); + struct symtab *sp = lookup(addname("__builtin_va_list"), 0); + p->n_sp = sp; + defid(p, TYPEDEF); + nfree(p); + } +#endif + complinit(); + +#ifdef STABS + if (gflag) { + stabs_file(argc ? argv[0] : ""); + stabs_init(); + } +#endif + + if (sspflag) + sspinit(); + + (void) yyparse(); + yyaccpt(); + + if (!nerrors) + lcommprint(); + +#ifdef STABS + if (gflag) + stabs_efile(argc ? argv[0] : ""); +#endif + + ejobcode( nerrors ? 1 : 0 ); + +#ifdef TIMING + (void)gettimeofday(&t2, NULL); + t2.tv_sec -= t1.tv_sec; + t2.tv_usec -= t1.tv_usec; + if (t2.tv_usec < 0) { + t2.tv_usec += 1000000; + t2.tv_sec -= 1; + } + fprintf(stderr, "ccom total time: %ld s %ld us\n", + t2.tv_sec, t2.tv_usec); +#endif + + if (sflag) + prtstats(); + return(nerrors?1:0); + +} + +void +prtstats(void) +{ + extern int nametabs, namestrlen, tmpallocsize, permallocsize; + extern int lostmem, arglistcnt, dimfuncnt, inlnodecnt, inlstatcnt; + extern int symtabcnt, suedefcnt; + + fprintf(stderr, "Name table entries: %d pcs\n", nametabs); + fprintf(stderr, "Name string size: %d B\n", namestrlen); + fprintf(stderr, "Permanent allocated memory: %d B\n", permallocsize); + fprintf(stderr, "Temporary allocated memory: %d B\n", tmpallocsize); + fprintf(stderr, "Lost memory: %d B\n", lostmem); + fprintf(stderr, "Argument list unions: %d pcs\n", arglistcnt); + fprintf(stderr, "Dimension/function unions: %d pcs\n", dimfuncnt); + fprintf(stderr, "Struct/union/enum blocks: %d pcs\n", suedefcnt); + fprintf(stderr, "Inline node count: %d pcs\n", inlnodecnt); + fprintf(stderr, "Inline control blocks: %d pcs\n", inlstatcnt); + fprintf(stderr, "Permanent symtab entries: %d pcs\n", symtabcnt); +} diff --git a/compilers/pcc/pcc-1.0.0/cc/ccom/optim.c b/compilers/pcc/pcc-1.0.0/cc/ccom/optim.c new file mode 100644 index 00000000..b2cec102 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/ccom/optim.c @@ -0,0 +1,385 @@ +/* $Id: optim.c,v 1.36.2.1 2011/03/01 17:40:21 ragge Exp $ */ +/* + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code and documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditionsand the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +# include "pass1.h" + +# define SWAP(p,q) {sp=p; p=q; q=sp;} +# define RCON(p) (p->n_right->n_op==ICON) +# define RO(p) p->n_right->n_op +# define RV(p) p->n_right->n_lval +# define LCON(p) (p->n_left->n_op==ICON) +# define LO(p) p->n_left->n_op +# define LV(p) p->n_left->n_lval + +/* remove left node */ +static NODE * +zapleft(NODE *p) +{ + NODE *q; + + q = p->n_left; + nfree(p->n_right); + nfree(p); + return q; +} + +/* + * fortran function arguments + */ +static NODE * +fortarg(NODE *p) +{ + if( p->n_op == CM ){ + p->n_left = fortarg( p->n_left ); + p->n_right = fortarg( p->n_right ); + return(p); + } + + while( ISPTR(p->n_type) ){ + p = buildtree( UMUL, p, NIL ); + } + return( optim(p) ); +} + + /* mapping relationals when the sides are reversed */ +short revrel[] ={ EQ, NE, GE, GT, LE, LT, UGE, UGT, ULE, ULT }; + +/* + * local optimizations, most of which are probably + * machine independent + */ +NODE * +optim(NODE *p) +{ + struct attr *ap; + int o, ty; + NODE *sp, *q; + int i; + TWORD t; + + t = BTYPE(p->n_type); + if( oflag ) return(p); + + ty = coptype(p->n_op); + if( ty == LTYPE ) return(p); + + if( ty == BITYPE ) p->n_right = optim(p->n_right); + p->n_left = optim(p->n_left); + + /* collect constants */ +again: o = p->n_op; + switch(o){ + + case SCONV: + case PCONV: + return( clocal(p) ); + + case FORTCALL: + p->n_right = fortarg( p->n_right ); + break; + + case ADDROF: + if (LO(p) == TEMP) + return p; + if( LO(p) != NAME ) cerror( "& error" ); + + if( !andable(p->n_left) ) return(p); + + LO(p) = ICON; + + setuleft: + /* paint over the type of the left hand side with the type of the top */ + p->n_left->n_type = p->n_type; + p->n_left->n_df = p->n_df; + p->n_left->n_ap = p->n_ap; + q = p->n_left; + nfree(p); + return q; + + case UMUL: + if (LO(p) == ADDROF) { + q = p->n_left->n_left; + nfree(p->n_left); + nfree(p); + return q; + } + if( LO(p) != ICON ) break; + LO(p) = NAME; + goto setuleft; + + case RS: + if (LCON(p) && RCON(p) && conval(p->n_left, o, p->n_right)) + goto zapright; + + ap = attr_find(p->n_ap, ATTR_BASETYP); + + if (LO(p) == RS && RCON(p->n_left) && RCON(p) && + (RV(p) + RV(p->n_left)) < ap->atypsz) { + /* two right-shift by constants */ + RV(p) += RV(p->n_left); + p->n_left = zapleft(p->n_left); + } +#if 0 + else if (LO(p) == LS && RCON(p->n_left) && RCON(p)) { + RV(p) -= RV(p->n_left); + if (RV(p) < 0) + o = p->n_op = LS, RV(p) = -RV(p); + p->n_left = zapleft(p->n_left); + } +#endif + if (RO(p) == ICON) { + if (RV(p) < 0) { + RV(p) = -RV(p); + p->n_op = LS; + goto again; + } +#ifdef notyet /* must check for side effects, --a >> 32; */ + if (RV(p) >= tsize(p->n_type, p->n_df, p->n_sue) && + ISUNSIGNED(p->n_type)) { /* ignore signed shifts */ + /* too many shifts */ + tfree(p->n_left); + nfree(p->n_right); + p->n_op = ICON; p->n_lval = 0; p->n_sp = NULL; + } else +#endif + /* avoid larger shifts than type size */ + if (RV(p) >= ap->atypsz) { + RV(p) = RV(p) % + attr_find(p->n_ap, ATTR_BASETYP)->atypsz; + werror("shift larger than type"); + } + if (RV(p) == 0) + p = zapleft(p); + } + break; + + case LS: + if (LCON(p) && RCON(p) && conval(p->n_left, o, p->n_right)) + goto zapright; + + ap = attr_find(p->n_ap, ATTR_BASETYP); + + if (LO(p) == LS && RCON(p->n_left) && RCON(p)) { + /* two left-shift by constants */ + RV(p) += RV(p->n_left); + p->n_left = zapleft(p->n_left); + } +#if 0 + else if (LO(p) == RS && RCON(p->n_left) && RCON(p)) { + RV(p) -= RV(p->n_left); + p->n_left = zapleft(p->n_left); + } +#endif + if (RO(p) == ICON) { + if (RV(p) < 0) { + RV(p) = -RV(p); + p->n_op = RS; + goto again; + } +#ifdef notyet /* must check for side effects */ + if (RV(p) >= tsize(p->n_type, p->n_df, p->n_sue)) { + /* too many shifts */ + tfree(p->n_left); + nfree(p->n_right); + p->n_op = ICON; p->n_lval = 0; p->n_sp = NULL; + } else +#endif + /* avoid larger shifts than type size */ + if (RV(p) >= ap->atypsz) { + RV(p) = RV(p) % + attr_find(p->n_ap, ATTR_BASETYP)->atypsz; + werror("shift larger than type"); + } + if (RV(p) == 0) + p = zapleft(p); + } + break; + + case MINUS: + if (LCON(p) && RCON(p) && p->n_left->n_sp == p->n_right->n_sp) { + /* link-time constants, but both are the same */ + /* solve it now by forgetting the symbols */ + p->n_left->n_sp = p->n_right->n_sp = NULL; + } + if( !nncon(p->n_right) ) break; + RV(p) = -RV(p); + o = p->n_op = PLUS; + + case MUL: + case PLUS: + case AND: + case OR: + case ER: + /* commutative ops; for now, just collect constants */ + /* someday, do it right */ + if( nncon(p->n_left) || ( LCON(p) && !RCON(p) ) ) + SWAP( p->n_left, p->n_right ); + /* make ops tower to the left, not the right */ + if( RO(p) == o ){ + NODE *t1, *t2, *t3; + t1 = p->n_left; + sp = p->n_right; + t2 = sp->n_left; + t3 = sp->n_right; + /* now, put together again */ + p->n_left = sp; + sp->n_left = t1; + sp->n_right = t2; + p->n_right = t3; + } + if(o == PLUS && LO(p) == MINUS && RCON(p) && RCON(p->n_left) && + conval(p->n_right, MINUS, p->n_left->n_right)){ + zapleft: + + q = p->n_left->n_left; + nfree(p->n_left->n_right); + nfree(p->n_left); + p->n_left = q; + } + if( RCON(p) && LO(p)==o && RCON(p->n_left) && + conval( p->n_right, o, p->n_left->n_right ) ){ + goto zapleft; + } + else if( LCON(p) && RCON(p) && conval( p->n_left, o, p->n_right ) ){ + zapright: + nfree(p->n_right); + q = makety(p->n_left, p->n_type, p->n_qual, + p->n_df, p->n_ap); + nfree(p); + return clocal(q); + } + + /* change muls to shifts */ + + if( o == MUL && nncon(p->n_right) && (i=ispow2(RV(p)))>=0){ + if( i == 0 ) { /* multiplication by 1 */ + goto zapright; + } + o = p->n_op = LS; + p->n_right->n_type = INT; + p->n_right->n_df = NULL; + RV(p) = i; + } + + /* change +'s of negative consts back to - */ + if( o==PLUS && nncon(p->n_right) && RV(p)<0 ){ + RV(p) = -RV(p); + o = p->n_op = MINUS; + } + + /* remove ops with RHS 0 */ + if ((o == PLUS || o == MINUS || o == OR || o == ER) && + nncon(p->n_right) && RV(p) == 0) { + goto zapright; + } + break; + + case DIV: + if( nncon( p->n_right ) && p->n_right->n_lval == 1 ) + goto zapright; + if (LCON(p) && RCON(p) && conval(p->n_left, DIV, p->n_right)) + goto zapright; + if (RCON(p) && ISUNSIGNED(p->n_type) && (i=ispow2(RV(p))) > 0) { + p->n_op = RS; + RV(p) = i; + q = p->n_right; + if(tsize(q->n_type, q->n_df, q->n_ap) > SZINT) + p->n_right = makety(q, INT, 0, 0, MKAP(INT)); + + break; + } + break; + + case MOD: + if (RCON(p) && ISUNSIGNED(p->n_type) && ispow2(RV(p)) > 0) { + p->n_op = AND; + RV(p) = RV(p) -1; + break; + } + break; + + case EQ: + case NE: + case LT: + case LE: + case GT: + case GE: + case ULT: + case ULE: + case UGT: + case UGE: + if( !LCON(p) ) break; + + /* exchange operands */ + + sp = p->n_left; + p->n_left = p->n_right; + p->n_right = sp; + p->n_op = revrel[p->n_op - EQ ]; + break; + +#ifdef notyet + case ASSIGN: + /* Simple test to avoid two branches */ + if (RO(p) != NE) + break; + q = p->n_right; + if (RCON(q) && RV(q) == 0 && LO(q) == AND && + RCON(q->n_left) && (i = ispow2(RV(q->n_left))) && + q->n_left->n_type == INT) { + q->n_op = RS; + RV(q) = i; + } + break; +#endif + } + + return(p); + } + +int +ispow2(CONSZ c) +{ + int i; + if( c <= 0 || (c&(c-1)) ) return(-1); + for( i=0; c>1; ++i) c >>= 1; + return(i); +} + +int +nncon( p ) NODE *p; { + /* is p a constant without a name */ + return( p->n_op == ICON && p->n_sp == NULL ); + } diff --git a/compilers/pcc/pcc-1.0.0/cc/ccom/pass1.h b/compilers/pcc/pcc-1.0.0/cc/ccom/pass1.h new file mode 100644 index 00000000..5a9ebb5d --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/ccom/pass1.h @@ -0,0 +1,611 @@ +/* $Id: pass1.h,v 1.215 2011/02/17 13:44:13 ragge Exp $ */ +/* + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code and documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditionsand the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include +#include +#include +#ifdef HAVE_STDINT_H +#include +#endif + +#ifndef MKEXT +#include "external.h" +#else +typedef unsigned int bittype; /* XXX - for basicblock */ +#endif +#include "manifest.h" + +#include "ccconfig.h" + +/* + * Storage classes + */ +#define SNULL 0 +#define AUTO 1 +#define EXTERN 2 +#define STATIC 3 +#define REGISTER 4 +#define EXTDEF 5 +/* #define LABEL 6*/ +/* #define ULABEL 7*/ +#define MOS 8 +#define PARAM 9 +#define STNAME 10 +#define MOU 11 +#define UNAME 12 +#define TYPEDEF 13 +/* #define FORTRAN 14 */ +#define ENAME 15 +#define MOE 16 +/* #define UFORTRAN 17 */ +#define USTATIC 18 + + /* field size is ORed in */ +#define FIELD 0200 +#define FLDSIZ 0177 +extern char *scnames(int); + +/* + * Symbol table flags + */ +#define SNORMAL 0 +#define STAGNAME 01 +#define SLBLNAME 02 +#define SMOSNAME 03 +#define SSTRING 04 +#define NSTYPES 05 +#define SMASK 07 + +/* #define SSET 00010 */ +/* #define SREF 00020 */ +#define SNOCREAT 00040 /* don't create a symbol in lookup() */ +#define STEMP 00100 /* Allocate symtab from temp or perm mem */ +#define SDYNARRAY 00200 /* symbol is dynamic array on stack */ +#define SINLINE 00400 /* function is of type inline */ +#define STNODE 01000 /* symbol shall be a temporary node */ +#define SASG 04000 /* symbol is assigned to already */ +#define SLOCAL1 010000 +#define SLOCAL2 020000 +#define SLOCAL3 040000 + + /* alignment of initialized quantities */ +#ifndef AL_INIT +#define AL_INIT ALINT +#endif + +struct rstack; +struct symtab; +union arglist; +#ifdef GCC_COMPAT +struct gcc_attr_pack; +#endif + +/* + * Dimension/prototype information. + * ddim > 0 holds the dimension of an array. + * ddim < 0 is a dynamic array and refers to a tempnode. + * ...unless: + * ddim == NOOFFSET, an array without dimenston, "[]" + * ddim == -1, dynamic array while building before defid. + */ +union dimfun { + int ddim; /* Dimension of an array */ + union arglist *dfun; /* Prototype index */ +}; + +/* + * Argument list member info when storing prototypes. + */ +union arglist { + TWORD type; + union dimfun *df; + struct attr *sap; +}; +#define TNULL INCREF(FARG) /* pointer to FARG -- impossible type */ +#define TELLIPSIS INCREF(INCREF(FARG)) + +/* + * Symbol table definition. + */ +struct symtab { + struct symtab *snext; /* link to other symbols in the same scope */ + int soffset; /* offset or value */ + char sclass; /* storage class */ + char slevel; /* scope level */ + short sflags; /* flags, see below */ + char *sname; /* Symbol name */ + char *soname; /* Written-out name */ + TWORD stype; /* type word */ + TWORD squal; /* qualifier word */ + union dimfun *sdf; /* ptr to the dimension/prototype array */ + struct attr *sap; /* the base type attribute list */ +}; + +struct attr2 { + struct attr *next; + int atype; + union aarg aa[2]; +}; + +#define ISSOU(ty) ((ty) == STRTY || (ty) == UNIONTY) +#define MKAP(type) ((struct attr *)&btattr[type]) +extern const struct attr2 btattr[]; + +/* + * External definitions + */ +struct swents { /* switch table */ + struct swents *next; /* Next struct in linked list */ + CONSZ sval; /* case value */ + int slab; /* associated label */ +}; +int mygenswitch(int, TWORD, struct swents **, int); + +extern int blevel; +extern int instruct, got_type; +extern int oldstyle; +extern int oflag; + +extern int lineno, nerrors; + +extern char *ftitle; +extern struct symtab *cftnsp; +extern int autooff, maxautooff, argoff, strucoff; +extern int brkflag; + +extern OFFSZ inoff; + +extern int reached; +extern int isinlining; +extern int xinline; + +extern int sdebug, idebug, pdebug; + +/* various labels */ +extern int brklab; +extern int contlab; +extern int flostat; +extern int retlab; + +/* pragma globals */ +extern int pragma_allpacked, pragma_packed, pragma_aligned; +extern char *pragma_renamed; + +/* + * Flags used in the (elementary) flow analysis ... + */ +#define FBRK 02 +#define FCONT 04 +#define FDEF 010 +#define FLOOP 020 + +/* mark an offset which is undefined */ + +#define NOOFFSET (-10201) + +/* declarations of various functions */ +extern NODE + *buildtree(int, NODE *, NODE *r), + *mkty(unsigned, union dimfun *, struct attr *), + *rstruct(char *, int), + *dclstruct(struct rstack *), + *strend(int gtype, char *), + *tymerge(NODE *, NODE *), + *stref(NODE *), + *offcon(OFFSZ, TWORD, union dimfun *, struct attr *), + *bcon(int), + *xbcon(CONSZ, struct symtab *, TWORD), + *bpsize(NODE *), + *convert(NODE *, int), + *pconvert(NODE *), + *oconvert(NODE *), + *ptmatch(NODE *), + *tymatch(NODE *), + *makety(NODE *, TWORD, TWORD, union dimfun *, struct attr *), + *block(int, NODE *, NODE *, TWORD, union dimfun *, struct attr *), + *doszof(NODE *), + *talloc(void), + *optim(NODE *), + *clocal(NODE *), + *ccopy(NODE *), + *tempnode(int, TWORD, union dimfun *, struct attr *), + *eve(NODE *), + *doacall(struct symtab *, NODE *, NODE *); +NODE *intprom(NODE *); +OFFSZ tsize(TWORD, union dimfun *, struct attr *), + psize(NODE *); +NODE * typenode(NODE *new); +void spalloc(NODE *, NODE *, OFFSZ); +char *exname(char *); +NODE *floatcon(char *); +NODE *fhexcon(char *); +NODE *bdty(int op, ...); +extern struct rstack *rpole; + +int oalloc(struct symtab *, int *); +void deflabel(char *, NODE *); +void gotolabel(char *); +unsigned int esccon(char **); +void inline_start(struct symtab *); +void inline_end(void); +void inline_addarg(struct interpass *); +void inline_ref(struct symtab *); +void inline_prtout(void); +void inline_args(struct symtab **, int); +NODE *inlinetree(struct symtab *, NODE *, NODE *); +void ftnarg(NODE *); +struct rstack *bstruct(char *, int, NODE *); +void moedef(char *); +void beginit(struct symtab *); +void simpleinit(struct symtab *, NODE *); +struct symtab *lookup(char *, int); +struct symtab *getsymtab(char *, int); +char *addstring(char *); +char *addname(char *); +void symclear(int); +struct symtab *hide(struct symtab *); +void soumemb(NODE *, char *, int); +int talign(unsigned int, struct attr *); +void bfcode(struct symtab **, int); +int chkftn(union arglist *, union arglist *); +void branch(int); +void cbranch(NODE *, NODE *); +void extdec(struct symtab *); +void defzero(struct symtab *); +int falloc(struct symtab *, int, NODE *); +TWORD ctype(TWORD); +void ninval(CONSZ, int, NODE *); +void infld(CONSZ, int, CONSZ); +void zbits(CONSZ, int); +void instring(struct symtab *); +void inwstring(struct symtab *); +void plabel(int); +void bjobcode(void); +void ejobcode(int); +void calldec(NODE *, NODE *); +int cisreg(TWORD); +char *tmpsprintf(char *, ...); +char *tmpvsprintf(char *, va_list); +void asginit(NODE *); +void desinit(NODE *); +void endinit(void); +void endictx(void); +void sspinit(void); +void sspstart(void); +void sspend(void); +void ilbrace(void); +void irbrace(void); +CONSZ scalinit(NODE *); +void p1print(char *, ...); +char *copst(int); +int cdope(int); +void myp2tree(NODE *); +void lcommprint(void); +void lcommdel(struct symtab *); +NODE *funcode(NODE *); +struct symtab *enumhd(char *); +NODE *enumdcl(struct symtab *); +NODE *enumref(char *); +CONSZ icons(NODE *); +CONSZ valcast(CONSZ v, TWORD t); +int mypragma(char *); +char *pragtok(char *); +int eat(int); +void fixdef(struct symtab *); +int cqual(TWORD, TWORD); +void defloc(struct symtab *); +int fldchk(int); +int nncon(NODE *); +void cunput(char); +NODE *nametree(struct symtab *sp); +void *inlalloc(int size); +void *blkalloc(int size); +void pass1_lastchance(struct interpass *); +void fldty(struct symtab *p); +int getlab(void); +struct suedef *sueget(struct suedef *p); +void complinit(void); +NODE *structref(NODE *p, int f, char *name); +NODE *cxop(int op, NODE *l, NODE *r); +NODE *imop(int op, NODE *l, NODE *r); +NODE *cxelem(int op, NODE *p); +NODE *cxconj(NODE *p); +NODE *cxret(NODE *p, NODE *q); +NODE *cast(NODE *p, TWORD t, TWORD q); +NODE *ccast(NODE *p, TWORD t, TWORD u, union dimfun *df, struct attr *sue); +int andable(NODE *); +int conval(NODE *, int, NODE *); +int ispow2(CONSZ); +void defid(NODE *q, int class); +void efcode(void); +void ecomp(NODE *p); +void cendarg(void); +int fldal(unsigned int); +int upoff(int size, int alignment, int *poff); +void nidcl(NODE *p, int class); +void eprint(NODE *, int, int *, int *); +int uclass(int class); +int notlval(NODE *); +void ecode(NODE *p); +void bccode(void); +void ftnend(void); +void dclargs(void); +int suemeq(struct attr *s1, struct attr *s2); +struct symtab *strmemb(struct attr *ap); +int yylex(void); +void yyerror(char *); +int pragmas_gcc(char *t); + +NODE *builtin_check(NODE *f, NODE *a); + +#ifdef SOFTFLOAT +typedef struct softfloat SF; +SF soft_neg(SF); +SF soft_cast(CONSZ v, TWORD); +SF soft_plus(SF, SF); +SF soft_minus(SF, SF); +SF soft_mul(SF, SF); +SF soft_div(SF, SF); +int soft_cmp_eq(SF, SF); +int soft_cmp_ne(SF, SF); +int soft_cmp_ge(SF, SF); +int soft_cmp_gt(SF, SF); +int soft_cmp_le(SF, SF); +int soft_cmp_lt(SF, SF); +int soft_isz(SF); +CONSZ soft_val(SF); +#define FLOAT_NEG(sf) soft_neg(sf) +#define FLOAT_CAST(v,t) soft_cast(v, t) +#define FLOAT_PLUS(x1,x2) soft_plus(x1, x2) +#define FLOAT_MINUS(x1,x2) soft_minus(x1, x2) +#define FLOAT_MUL(x1,x2) soft_mul(x1, x2) +#define FLOAT_DIV(x1,x2) soft_div(x1, x2) +#define FLOAT_ISZERO(sf) soft_isz(sf) +#define FLOAT_VAL(sf) soft_val(sf) +#define FLOAT_EQ(x1,x2) soft_cmp_eq(x1, x2) +#define FLOAT_NE(x1,x2) soft_cmp_ne(x1, x2) +#define FLOAT_GE(x1,x2) soft_cmp_ge(x1, x2) +#define FLOAT_GT(x1,x2) soft_cmp_gt(x1, x2) +#define FLOAT_LE(x1,x2) soft_cmp_le(x1, x2) +#define FLOAT_LT(x1,x2) soft_cmp_lt(x1, x2) +#else +#define FLOAT_NEG(p) -(p) +#define FLOAT_CAST(p,v) (ISUNSIGNED(v) ? \ + (long double)(U_CONSZ)(p) : (long double)(CONSZ)(p)) +#define FLOAT_PLUS(x1,x2) (x1) + (x2) +#define FLOAT_MINUS(x1,x2) (x1) - (x2) +#define FLOAT_MUL(x1,x2) (x1) * (x2) +#define FLOAT_DIV(x1,x2) (x1) / (x2) +#define FLOAT_ISZERO(p) (p) == 0.0 +#define FLOAT_VAL(p) (CONSZ)(p) +#define FLOAT_EQ(x1,x2) (x1) == (x2) +#define FLOAT_NE(x1,x2) (x1) != (x2) +#define FLOAT_GE(x1,x2) (x1) >= (x2) +#define FLOAT_GT(x1,x2) (x1) > (x2) +#define FLOAT_LE(x1,x2) (x1) <= (x2) +#define FLOAT_LT(x1,x2) (x1) < (x2) +#endif + +enum { ATTR_NONE, + + /* PCC used attributes */ + ATTR_COMPLEX, /* Internal definition of complex */ + ATTR_BASETYP, /* Internal; see below */ + ATTR_QUALTYP, /* Internal; const/volatile, see below */ + ATTR_STRUCT, /* Internal; element list */ +#define ATTR_MAX ATTR_STRUCT + +#ifdef GCC_COMPAT + /* type attributes */ + GCC_ATYP_ALIGNED, + GCC_ATYP_PACKED, + GCC_ATYP_SECTION, + GCC_ATYP_TRANSP_UNION, + GCC_ATYP_UNUSED, + GCC_ATYP_DEPRECATED, + GCC_ATYP_MAYALIAS, + + /* variable attributes */ + GCC_ATYP_MODE, + + /* function attributes */ + GCC_ATYP_NORETURN, + GCC_ATYP_FORMAT, + GCC_ATYP_NONNULL, + GCC_ATYP_SENTINEL, + GCC_ATYP_WEAK, + GCC_ATYP_FORMATARG, + GCC_ATYP_GNU_INLINE, + GCC_ATYP_MALLOC, + GCC_ATYP_NOTHROW, + GCC_ATYP_CONST, + GCC_ATYP_PURE, + GCC_ATYP_CONSTRUCTOR, + GCC_ATYP_DESTRUCTOR, + GCC_ATYP_VISIBILITY, + GCC_ATYP_STDCALL, + GCC_ATYP_CDECL, + GCC_ATYP_WARN_UNUSED_RESULT, + GCC_ATYP_USED, + GCC_ATYP_NO_INSTR_FUN, + GCC_ATYP_NOINLINE, + GCC_ATYP_ALIAS, + GCC_ATYP_WEAKREF, + GCC_ATYP_ALLOCSZ, + GCC_ATYP_ALW_INL, + GCC_ATYP_TLSMODEL, + GCC_ATYP_ALIASWEAK, + + /* other stuff */ + GCC_ATYP_BOUNDED, /* OpenBSD extra boundary checks */ + + GCC_ATYP_MAX +#endif +}; + + +/* + * ATTR_BASETYP has the following layout: + * aa[0].iarg has size + * aa[1].iarg has alignment + * ATTR_QUALTYP has the following layout: + * aa[0].iarg has CON/VOL + FUN/ARY/PTR + * Not defined yet... + * aa[3].iarg is dimension for arrays (XXX future) + * aa[3].varg is function defs for functions. + */ +#define atypsz aa[0].iarg +#define aalign aa[1].iarg + +/* + * ATTR_STRUCT member list. + */ +#define amlist aa[0].varg +#define strattr(x) (attr_find(x, ATTR_STRUCT)) + +#define iarg(x) aa[x].iarg +#define sarg(x) aa[x].sarg +#define varg(x) aa[x].varg + +void gcc_init(void); +int gcc_keyword(char *, NODE **); +struct attr *gcc_attr_parse(NODE *); +void gcc_tcattrfix(NODE *); +struct gcc_attrib *gcc_get_attr(struct suedef *, int); +void dump_attr(struct attr *gap); + +struct attr *attr_add(struct attr *orig, struct attr *new); +struct attr *attr_new(int, int); +struct attr *attr_find(struct attr *, int); +struct attr *attr_copy(struct attr *src, struct attr *dst, int nelem); +struct attr *attr_dup(struct attr *ap, int n); + +#ifdef STABS +void stabs_init(void); +void stabs_file(char *); +void stabs_efile(char *); +void stabs_line(int); +void stabs_rbrac(int); +void stabs_lbrac(int); +void stabs_func(struct symtab *); +void stabs_newsym(struct symtab *); +void stabs_chgsym(struct symtab *); +void stabs_struct(struct symtab *, struct attr *); +#endif + +#ifndef CHARCAST +/* to make character constants into character connstants */ +/* this is a macro to defend against cross-compilers, etc. */ +#define CHARCAST(x) (char)(x) +#endif + +/* sometimes int is smaller than pointers */ +#if SZPOINT(CHAR) <= SZINT +#define INTPTR INT +#elif SZPOINT(CHAR) <= SZLONG +#define INTPTR LONG +#elif SZPOINT(CHAR) <= SZLONGLONG +#define INTPTR LONGLONG +#else +#error int size unknown +#endif + +/* + * C compiler first pass extra defines. + */ +#define QUALIFIER (MAXOP+1) +#define CLASS (MAXOP+2) +#define RB (MAXOP+3) +#define DOT (MAXOP+4) +#define ELLIPSIS (MAXOP+5) +#define TYPE (MAXOP+6) +#define LB (MAXOP+7) +#define COMOP (MAXOP+8) +#define QUEST (MAXOP+9) +#define COLON (MAXOP+10) +#define ANDAND (MAXOP+11) +#define OROR (MAXOP+12) +#define NOT (MAXOP+13) +#define CAST (MAXOP+14) +#define STRING (MAXOP+15) + +/* The following must be in the same order as their NOASG counterparts */ +#define PLUSEQ (MAXOP+16) +#define MINUSEQ (MAXOP+17) +#define DIVEQ (MAXOP+18) +#define MODEQ (MAXOP+19) +#define MULEQ (MAXOP+20) +#define ANDEQ (MAXOP+21) +#define OREQ (MAXOP+22) +#define EREQ (MAXOP+23) +#define LSEQ (MAXOP+24) +#define RSEQ (MAXOP+25) + +#define UNASG (-(PLUSEQ-PLUS))+ + +#define INCR (MAXOP+26) +#define DECR (MAXOP+27) +#define SZOF (MAXOP+28) +#define CLOP (MAXOP+29) +#define ATTRIB (MAXOP+30) +#define XREAL (MAXOP+31) +#define XIMAG (MAXOP+32) +#define TYMERGE (MAXOP+33) + + +/* + * The following types are only used in pass1. + */ +#define SIGNED (MAXTYPES+1) +#define BOOL (MAXTYPES+2) +#define FIMAG (MAXTYPES+3) +#define IMAG (MAXTYPES+4) +#define LIMAG (MAXTYPES+5) +#define FCOMPLEX (MAXTYPES+6) +#define COMPLEX (MAXTYPES+7) +#define LCOMPLEX (MAXTYPES+8) +#define ENUMTY (MAXTYPES+9) + +#define ISFTY(x) ((x) >= FLOAT && (x) <= LDOUBLE) +#define ISCTY(x) ((x) >= FCOMPLEX && (x) <= LCOMPLEX) +#define ISITY(x) ((x) >= FIMAG && (x) <= LIMAG) +#define ANYCX(p) (p->n_type == STRTY && attr_find(p->n_ap, ATTR_COMPLEX)) + +#define coptype(o) (cdope(o)&TYFLG) +#define clogop(o) (cdope(o)&LOGFLG) +#define casgop(o) (cdope(o)&ASGFLG) + diff --git a/compilers/pcc/pcc-1.0.0/cc/ccom/pftn.c b/compilers/pcc/pcc-1.0.0/cc/ccom/pftn.c new file mode 100644 index 00000000..a77c4929 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/ccom/pftn.c @@ -0,0 +1,3271 @@ +/* $Id: pftn.c,v 1.311 2011/02/20 10:19:07 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code and documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditionsand the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Many changes from the 32V sources, among them: + * - New symbol table manager (moved to another file). + * - Prototype saving/checks. + */ + +# include "pass1.h" + +#include "cgram.h" + +struct symtab *cftnsp; +int arglistcnt, dimfuncnt; /* statistics */ +int symtabcnt, suedefcnt; /* statistics */ +int autooff, /* the next unused automatic offset */ + maxautooff, /* highest used automatic offset in function */ + argoff; /* the next unused argument offset */ +int retlab = NOLAB; /* return label for subroutine */ +int brklab; +int contlab; +int flostat; +int blevel; +int reached, prolab; + +struct params; + +#define MKTY(p, t, d, s) r = talloc(); *r = *p; \ + r = argcast(r, t, d, s); *p = *r; nfree(r); + +/* + * Linked list stack while reading in structs. + */ +struct rstack { + struct rstack *rnext; + int rsou; + int rstr; + struct symtab *rsym; + struct symtab *rb; + struct attr *ap; + int flags; +#define LASTELM 1 +} *rpole; + +/* + * Linked list for parameter (and struct elements) declaration. + */ +static struct params { + struct params *next, *prev; + struct symtab *sym; +} *lpole, *lparam; +static int nparams; + +/* defines used for getting things off of the initialization stack */ + +NODE *arrstk[10]; +int arrstkp; +static int intcompare; +NODE *parlink; + +void fixtype(NODE *p, int class); +int fixclass(int class, TWORD type); +static void dynalloc(struct symtab *p, int *poff); +static void evalidx(struct symtab *p); +int isdyn(struct symtab *p); +void inforce(OFFSZ n); +void vfdalign(int n); +static void ssave(struct symtab *); +static void alprint(union arglist *al, int in); +static void lcommadd(struct symtab *sp); +static NODE *mkcmplx(NODE *p, TWORD dt); +extern int fun_inline; + +int ddebug = 0; + +/* + * Declaration of an identifier. Handles redeclarations, hiding, + * incomplete types and forward declarations. + * + * q is a TYPE node setup after parsing with n_type, n_df and n_ap. + * n_sp is a pointer to the not-yet initalized symbol table entry + * unless it's a redeclaration or supposed to hide a variable. + */ + +void +defid(NODE *q, int class) +{ + struct attr *ap; + struct symtab *p; + TWORD type, qual; + TWORD stp, stq; + int scl; + union dimfun *dsym, *ddef; + int slev, temp, changed; + + if (q == NIL) + return; /* an error was detected */ + + p = q->n_sp; + + if (p->sname == NULL) + cerror("defining null identifier"); + +#ifdef PCC_DEBUG + if (ddebug) { + printf("defid(%s (%p), ", p->sname, p); + tprint(stdout, q->n_type, q->n_qual); + printf(", %s, (%p)), level %d\n\t", scnames(class), + q->n_df, blevel); + dump_attr(q->n_ap); + } +#endif + + fixtype(q, class); + + type = q->n_type; + qual = q->n_qual; + class = fixclass(class, type); + + stp = p->stype; + stq = p->squal; + slev = p->slevel; + +#ifdef PCC_DEBUG + if (ddebug) { + printf(" modified to "); + tprint(stdout, type, qual); + printf(", %s\n", scnames(class)); + printf(" previous def'n: "); + tprint(stdout, stp, stq); + printf(", %s, (%p,%p)), level %d\n", + scnames(p->sclass), p->sdf, p->sap, slev); + } +#endif + + if (blevel == 1) { + switch (class) { + default: + if (!(class&FIELD) && !ISFTN(type)) + uerror("declared argument %s missing", + p->sname ); + case MOS: + case MOU: + case TYPEDEF: + case PARAM: + ; + } + } + + if (stp == UNDEF) + goto enter; /* New symbol */ + + if (type != stp) + goto mismatch; + + if (blevel > slev && (class == AUTO || class == REGISTER)) + /* new scope */ + goto mismatch; + + /* + * test (and possibly adjust) dimensions. + * also check that prototypes are correct. + */ + dsym = p->sdf; + ddef = q->n_df; + changed = 0; + for (temp = type; temp & TMASK; temp = DECREF(temp)) { + if (ISARY(temp)) { + if (dsym->ddim == NOOFFSET) { + dsym->ddim = ddef->ddim; + changed = 1; + } else if (ddef->ddim != NOOFFSET && + dsym->ddim!=ddef->ddim) { + goto mismatch; + } + ++dsym; + ++ddef; + } else if (ISFTN(temp)) { + /* add a late-defined prototype here */ + if (cftnsp == NULL && dsym->dfun == NULL) + dsym->dfun = ddef->dfun; + if (!oldstyle && ddef->dfun != NULL && + chkftn(dsym->dfun, ddef->dfun)) + uerror("declaration doesn't match prototype"); + dsym++, ddef++; + } + } +#ifdef STABS + if (changed && gflag) + stabs_chgsym(p); /* symbol changed */ +#endif + + /* check that redeclarations are to the same structure */ + if (temp == STRTY || temp == UNIONTY) { + if (strmemb(p->sap) != strmemb(q->n_ap)) + goto mismatch; + } + + scl = p->sclass; + +#ifdef PCC_DEBUG + if (ddebug) + printf(" previous class: %s\n", scnames(scl)); +#endif + + /* + * Its allowed to add attributes to existing declarations. + * Be care ful though not to trash existing attributes. + */ + if (p->sap->atype <= ATTR_MAX) { + /* nothing special, just overwrite */ + p->sap = q->n_ap; + } else { + for (ap = q->n_ap; ap; ap = ap->next) { + if (ap->atype > ATTR_MAX) + p->sap = attr_add(p->sap, attr_dup(ap, 3)); + } + } + + if (class & FIELD) + return; + switch(class) { + + case EXTERN: + if (pragma_renamed) + p->soname = pragma_renamed; + pragma_renamed = NULL; + switch( scl ){ + case STATIC: + case USTATIC: + if( slev==0 ) + goto done; + break; + case EXTDEF: + case EXTERN: + goto done; + case SNULL: + if (p->sflags & SINLINE) { + p->sclass = EXTDEF; + inline_ref(p); + goto done; + } + break; + } + break; + + case STATIC: + if (scl==USTATIC || (scl==EXTERN && blevel==0)) { + p->sclass = STATIC; + goto done; + } + if (changed || (scl == STATIC && blevel == slev)) + goto done; /* identical redeclaration */ + break; + + case USTATIC: + if (scl==STATIC || scl==USTATIC) + goto done; + break; + + case TYPEDEF: + if (scl == class) + goto done; + break; + + case MOU: + case MOS: + goto done; + + case EXTDEF: + switch (scl) { + case EXTERN: + p->sclass = EXTDEF; + goto done; + case USTATIC: + p->sclass = STATIC; + goto done; + case SNULL: + /* + * Handle redeclarations of inlined functions. + * This is allowed if the previous declaration is of + * type gnu_inline. + */ + if (attr_find(p->sap, GCC_ATYP_GNU_INLINE)) + goto done; + break; + } + break; + + case AUTO: + case REGISTER: + break; /* mismatch.. */ + case SNULL: + if (fun_inline && ISFTN(type)) + goto done; + break; + } + + mismatch: + + /* + * Only allowed for automatic variables. + */ + if (blevel <= slev || class == EXTERN) { + uerror("redeclaration of %s", p->sname); + return; + } + q->n_sp = p = hide(p); + + enter: /* make a new entry */ + +#ifdef PCC_DEBUG + if(ddebug) + printf(" new entry made\n"); +#endif + if (type < BTMASK && (ap = attr_find(q->n_ap, GCC_ATYP_MODE))) { + int u = ISUNSIGNED(type); + type = u ? ENUNSIGN(ap->iarg(0)) : ap->iarg(0); + if (type != XTYPE) { + for (ap = q->n_ap; + ap->next->atype != ATTR_BASETYP; ap = ap->next) + ; + ap->next = MKAP(type); + } else + uerror("fix XTYPE basetyp"); + } + p->stype = type; + p->squal = qual; + p->sclass = (char)class; + p->slevel = (char)blevel; + p->soffset = NOOFFSET; + if (q->n_ap == NULL) + cerror("q->n_ap == NULL"); + p->sap = attr_add(q->n_ap, p->sap); + + /* copy dimensions */ + p->sdf = q->n_df; + /* Do not save param info for old-style functions */ + if (ISFTN(type) && oldstyle) + p->sdf->dfun = NULL; + + if (arrstkp) + evalidx(p); + + /* allocate offsets */ + if (class&FIELD) { + (void) falloc(p, class&FLDSIZ, NIL); /* new entry */ + } else switch (class) { + + case REGISTER: + cerror("register var"); + + case AUTO: + if (isdyn(p)) { + p->sflags |= SDYNARRAY; + dynalloc(p, &autooff); + } else + oalloc(p, &autooff); + break; + + case PARAM: + oalloc(p, &argoff); + break; + + case STATIC: + case EXTDEF: + case EXTERN: + p->soffset = getlab(); + if (pragma_renamed) + p->soname = pragma_renamed; + pragma_renamed = NULL; + break; + + case MOU: + rpole->rstr = 0; + /* FALLTHROUGH */ + case MOS: + oalloc(p, &rpole->rstr); + if (class == MOU) + rpole->rstr = 0; + break; + case SNULL: +#ifdef notdef + if (fun_inline) { + p->slevel = 1; + p->soffset = getlab(); + } +#endif + break; + } + +#ifdef STABS + if (gflag) + stabs_newsym(p); +#endif + +done: + fixdef(p); /* Leave last word to target */ +#ifndef HAVE_WEAKREF + { + struct attr *at; + + /* Refer renamed function */ + if ((at = attr_find(p->sap, GCC_ATYP_WEAKREF))) + p->soname = at->sarg(0); + } +#endif +#ifdef PCC_DEBUG + if (ddebug) { + printf( " sdf, offset: %p, %d\n\t", + p->sdf, p->soffset); + dump_attr(p->sap); + } +#endif +} + +void +ssave(struct symtab *sym) +{ + struct params *p; + + p = tmpalloc(sizeof(struct params)); + p->next = NULL; + p->sym = sym; + + if ((p->prev = lparam) == NULL) + lpole = p; + else + lparam->next = p; + lparam = p; +} + +/* + * end of function + */ +void +ftnend() +{ + extern NODE *cftnod; + extern struct savbc *savbc; + extern struct swdef *swpole; + extern int tvaloff; + char *c; + + if (retlab != NOLAB && nerrors == 0) { /* inside a real function */ + plabel(retlab); + if (cftnod) + ecomp(buildtree(FORCE, cftnod, NIL)); + efcode(); /* struct return handled here */ + if ((c = cftnsp->soname) == NULL) + c = addname(exname(cftnsp->sname)); + SETOFF(maxautooff, ALCHAR); + send_passt(IP_EPILOG, maxautooff/SZCHAR, c, + cftnsp->stype, cftnsp->sclass == EXTDEF, retlab, tvaloff); + } + + cftnod = NIL; + tcheck(); + brklab = contlab = retlab = NOLAB; + flostat = 0; + if (nerrors == 0) { + if (savbc != NULL) + cerror("bcsave error"); + if (lparam != NULL) + cerror("parameter reset error"); + if (swpole != NULL) + cerror("switch error"); + } + savbc = NULL; + lparam = NULL; + cftnsp = NULL; + maxautooff = autooff = AUTOINIT; + reached = 1; + + if (isinlining) + inline_end(); + inline_prtout(); + + tmpfree(); /* Release memory resources */ +} + +static struct symtab nulsym = { + NULL, 0, 0, 0, 0, "null", "null", INT, 0, NULL, NULL +}; + +void +dclargs() +{ + union dimfun *df; + union arglist *al, *al2, *alb; + struct params *a; + struct symtab *p, **parr = NULL; /* XXX gcc */ + int i; + + /* + * Deal with fun(void) properly. + */ + if (nparams == 1 && lparam->sym && lparam->sym->stype == VOID) + goto done; + + /* + * Generate a list for bfcode(). + * Parameters were pushed in reverse order. + */ + if (nparams != 0) + parr = tmpalloc(sizeof(struct symtab *) * nparams); + + if (nparams) + for (a = lparam, i = 0; a != NULL; a = a->prev) { + p = a->sym; + parr[i++] = p; + if (p == NULL) { + uerror("parameter %d name missing", i); + p = &nulsym; /* empty symtab */ + } + if (p->stype == FARG) { + p->stype = INT; + p->sap = MKAP(INT); + } + if (ISARY(p->stype)) { + p->stype += (PTR-ARY); + p->sdf++; + } else if (ISFTN(p->stype)) { + werror("function declared as argument"); + p->stype = INCREF(p->stype); + } +#ifdef STABS + if (gflag) + stabs_newsym(p); +#endif + } + if (oldstyle && (df = cftnsp->sdf) && (al = df->dfun)) { + /* + * Check against prototype of oldstyle function. + */ + alb = al2 = tmpalloc(sizeof(union arglist) * nparams * 3 + 1); + for (i = 0; i < nparams; i++) { + TWORD type = parr[i]->stype; + (al2++)->type = type; + if (ISSOU(BTYPE(type))) + (al2++)->sap = parr[i]->sap; + while (!ISFTN(type) && !ISARY(type) && type > BTMASK) + type = DECREF(type); + if (type > BTMASK) + (al2++)->df = parr[i]->sdf; + } + al2->type = TNULL; + intcompare = 1; + if (chkftn(al, alb)) + uerror("function doesn't match prototype"); + intcompare = 0; + + } + + if (oldstyle && nparams) { + /* Must recalculate offset for oldstyle args here */ + argoff = ARGINIT; + for (i = 0; i < nparams; i++) { + parr[i]->soffset = NOOFFSET; + oalloc(parr[i], &argoff); + } + } + +done: cendarg(); + + plabel(prolab); /* after prolog, used in optimization */ + retlab = getlab(); + bfcode(parr, nparams); + if (fun_inline && + (xinline || attr_find(cftnsp->sap, GCC_ATYP_ALW_INL))) + inline_args(parr, nparams); + plabel(getlab()); /* used when spilling */ + if (parlink) + ecomp(parlink); + parlink = NIL; + lparam = NULL; + nparams = 0; + symclear(1); /* In case of function pointer args */ +} + +/* + * basic attributes for structs and enums + */ +static struct attr * +seattr(void) +{ + return attr_add(attr_new(ATTR_BASETYP, 4), attr_new(ATTR_STRUCT, 1)); +} + +/* + * Struct/union/enum symtab construction. + */ +static void +defstr(struct symtab *sp, int class) +{ + sp->sclass = (char)class; + if (class == STNAME) + sp->stype = STRTY; + else if (class == UNAME) + sp->stype = UNIONTY; + else if (class == ENAME) + sp->stype = ENUMTY; +} + +/* + * Declare a struct/union/enum tag. + * If not found, create a new tag with UNDEF type. + */ +static struct symtab * +deftag(char *name, int class) +{ + struct symtab *sp; + + if ((sp = lookup(name, STAGNAME))->sap == NULL) { + /* New tag */ + defstr(sp, class); + } else if (sp->sclass != class) + uerror("tag %s redeclared", name); + return sp; +} + +/* + * reference to a structure or union, with no definition + */ +NODE * +rstruct(char *tag, int soru) +{ + struct symtab *sp; + + sp = deftag(tag, soru); + if (sp->sap == NULL) + sp->sap = seattr(); + return mkty(sp->stype, 0, sp->sap); +} + +static int enumlow, enumhigh; +int enummer; + +/* + * Declare a member of enum. + */ +void +moedef(char *name) +{ + struct symtab *sp; + + sp = lookup(name, SNORMAL); + if (sp->stype == UNDEF || (sp->slevel < blevel)) { + if (sp->stype != UNDEF) + sp = hide(sp); + sp->stype = INT; /* always */ + sp->sap = MKAP(INT); + sp->sclass = MOE; + sp->soffset = enummer; + } else + uerror("%s redeclared", name); + if (enummer < enumlow) + enumlow = enummer; + if (enummer > enumhigh) + enumhigh = enummer; + enummer++; +} + +/* + * Declare an enum tag. Complain if already defined. + */ +struct symtab * +enumhd(char *name) +{ + struct attr *ap; + struct symtab *sp; + + enummer = enumlow = enumhigh = 0; + if (name == NULL) + return NULL; + + sp = deftag(name, ENAME); + if (sp->stype != ENUMTY) { + if (sp->slevel == blevel) + uerror("%s redeclared", name); + sp = hide(sp); + defstr(sp, ENAME); + } + if (sp->sap == NULL) + sp->sap = seattr(); + ap = attr_find(sp->sap, ATTR_STRUCT); + ap->amlist = sp; + return sp; +} + +/* + * finish declaration of an enum + */ +NODE * +enumdcl(struct symtab *sp) +{ + struct attr *ap; + NODE *p; + TWORD t; + +#ifdef ENUMSIZE + t = ENUMSIZE(enumhigh, enumlow); +#else + if (enumhigh <= MAX_CHAR && enumlow >= MIN_CHAR) + t = ctype(CHAR); + else if (enumhigh <= MAX_SHORT && enumlow >= MIN_SHORT) + t = ctype(SHORT); + else + t = ctype(INT); +#endif + + if (sp) { + sp->stype = t; + ap = attr_find(sp->sap, ATTR_BASETYP); + ap->atypsz = (MKAP(t))->atypsz; + ap->aalign = (MKAP(t))->aalign; + ap = sp->sap; + } else + ap = MKAP(t); + p = mkty(t, 0, ap); + p->n_sp = sp; + return p; +} + +/* + * Handle reference to an enum + */ +NODE * +enumref(char *name) +{ + struct symtab *sp; + NODE *p; + + sp = lookup(name, STAGNAME); + +#ifdef notdef + /* + * 6.7.2.3 Clause 2: + * "A type specifier of the form 'enum identifier' without an + * enumerator list shall only appear after the type it specifies + * is complete." + */ + if (sp->sclass != ENAME) + uerror("enum %s undeclared", name); +#endif + if (sp->sclass == SNULL) { + /* declare existence of enum */ + sp = enumhd(name); + sp->stype = ENUMTY; + } + + p = mkty(sp->stype, 0, sp->sap); + p->n_sp = sp; + return p; +} + +/* + * begining of structure or union declaration + * It's an error if this routine is called twice with the same struct. + */ +struct rstack * +bstruct(char *name, int soru, NODE *gp) +{ + struct rstack *r; + struct symtab *sp; + struct attr *ap, *gap; + + gap = gp ? gcc_attr_parse(gp) : NULL; + + if (name != NULL) { + sp = deftag(name, soru); + if (sp->sap == NULL) + sp->sap = seattr(); + ap = attr_find(sp->sap, ATTR_BASETYP); + if (ap->aalign != 0) { + if (sp->slevel < blevel) { + sp = hide(sp); + defstr(sp, soru); + sp->sap = seattr(); + } else + uerror("%s redeclared", name); + } + gap = sp->sap = attr_add(sp->sap, gap); + } else { + gap = attr_add(seattr(), gap); + sp = NULL; + } + + r = tmpcalloc(sizeof(struct rstack)); + r->rsou = soru; + r->rsym = sp; + r->rb = NULL; + r->ap = gap; + r->rnext = rpole; + rpole = r; + + return r; +} + +/* + * Called after a struct is declared to restore the environment. + * - If ALSTRUCT is defined, this will be the struct alignment and the + * struct size will be a multiple of ALSTRUCT, otherwise it will use + * the alignment of the largest struct member. + */ +NODE * +dclstruct(struct rstack *r) +{ + NODE *n; + struct attr *aps, *apb; + struct symtab *sp; + int al, sa, sz, coff; + + apb = attr_find(r->ap, ATTR_BASETYP); + aps = attr_find(r->ap, ATTR_STRUCT); + aps->amlist = r->rb; + +#ifdef ALSTRUCT + al = ALSTRUCT; +#else + al = ALCHAR; +#endif + + /* + * extract size and alignment, calculate offsets + */ + coff = 0; + for (sp = r->rb; sp; sp = sp->snext) { + sa = talign(sp->stype, sp->sap); + if (sp->sclass & FIELD) + sz = sp->sclass&FLDSIZ; + else + sz = (int)tsize(sp->stype, sp->sdf, sp->sap); + if (sz > rpole->rstr) + rpole->rstr = sz; /* for use with unions */ + /* + * set al, the alignment, to the lcm of the alignments + * of the members. + */ + SETOFF(al, sa); + } + + SETOFF(rpole->rstr, al); + + apb->atypsz = rpole->rstr; + apb->aalign = al; + +#ifdef PCC_DEBUG + if (ddebug) { + printf("dclstruct(%s): size=%d, align=%d\n", + r->rsym ? r->rsym->sname : "??", + apb->atypsz, apb->aalign); + } + if (ddebug>1) { + printf("\tsize %d align %d link %p\n", + apb->atypsz, apb->aalign, aps->amlist); + for (sp = aps->amlist; sp != NULL; sp = sp->snext) { + printf("\tmember %s(%p)\n", sp->sname, sp); + } + } +#endif + +#ifdef STABS + if (gflag) + stabs_struct(r->rsym, r->ap); +#endif + + rpole = r->rnext; + n = mkty(r->rsou == STNAME ? STRTY : UNIONTY, 0, r->ap); + + n->n_qual |= 1; /* definition place XXX used by attributes */ + return n; +} + +/* + * Add a new member to the current struct or union being declared. + */ +void +soumemb(NODE *n, char *name, int class) +{ + struct symtab *sp, *lsp; + int incomp; + TWORD t; + + if (rpole == NULL) + cerror("soumemb"); + + /* check if tag name exists */ + lsp = NULL; + for (sp = rpole->rb; sp != NULL; lsp = sp, sp = sp->snext) + if (*name != '*' && sp->sname == name) + uerror("redeclaration of %s", name); + + sp = getsymtab(name, SMOSNAME); + if (rpole->rb == NULL) + rpole->rb = sp; + else + lsp->snext = sp; +#ifdef GCC_COMPAT + if (n->n_op == CM) + cerror("soumemb CM"); +#endif + n->n_sp = sp; + if ((class & FIELD) == 0) + class = rpole->rsou == STNAME ? MOS : MOU; + defid(n, class); + + /* + * 6.7.2.1 clause 16: + * "...the last member of a structure with more than one + * named member may have incomplete array type;" + */ + if (ISARY(sp->stype) && sp->sdf->ddim == NOOFFSET) + incomp = 1; + else + incomp = 0; + if ((rpole->flags & LASTELM) || (rpole->rb == sp && incomp == 1)) + uerror("incomplete array in struct"); + if (incomp == 1) + rpole->flags |= LASTELM; + + /* + * 6.7.2.1 clause 2: + * "...such a structure shall not be a member of a structure + * or an element of an array." + */ + t = sp->stype; + if (rpole->rsou != STNAME || BTYPE(t) != STRTY) + return; /* not for unions */ + while (ISARY(t)) + t = DECREF(t); + if (ISPTR(t)) + return; + + if ((lsp = strmemb(sp->sap)) != NULL) { + for (; lsp->snext; lsp = lsp->snext) + ; + if (ISARY(lsp->stype) && lsp->snext && + lsp->sdf->ddim == NOOFFSET) + uerror("incomplete struct in struct"); + } +} + +/* + * error printing routine in parser + */ +void +yyerror(char *s) +{ + uerror(s); +} + +void yyaccpt(void); +void +yyaccpt(void) +{ + ftnend(); +} + +/* + * p is top of type list given to tymerge later. + * Find correct CALL node and declare parameters from there. + */ +void +ftnarg(NODE *p) +{ + NODE *q; + +#ifdef PCC_DEBUG + if (ddebug > 2) + printf("ftnarg(%p)\n", p); +#endif + /* + * Push argument symtab entries onto param stack in reverse order, + * due to the nature of the stack it will be reclaimed correct. + */ + for (; p->n_op != NAME; p = p->n_left) { + if (p->n_op == UCALL && p->n_left->n_op == NAME) + return; /* Nothing to enter */ + if (p->n_op == CALL && p->n_left->n_op == NAME) + break; + } + + p = p->n_right; + while (p->n_op == CM) { + q = p->n_right; + if (q->n_op != ELLIPSIS) { + ssave(q->n_sp); + nparams++; +#ifdef PCC_DEBUG + if (ddebug > 2) + printf(" saving sym %s (%p) from (%p)\n", + q->n_sp->sname, q->n_sp, q); +#endif + } + p = p->n_left; + } + ssave(p->n_sp); + if (p->n_type != VOID) + nparams++; + +#ifdef PCC_DEBUG + if (ddebug > 2) + printf(" saving sym %s (%p) from (%p)\n", + nparams ? p->n_sp->sname : "", p->n_sp, p); +#endif +} + +/* + * compute the alignment of an object with type ty, sizeoff index s + */ +int +talign(unsigned int ty, struct attr *apl) +{ + struct attr *al; + int i; + + if (ISPTR(ty)) + return(ALPOINT); /* shortcut */ + + if(apl == NULL && ty!=INT && ty!=CHAR && ty!=SHORT && + ty!=UNSIGNED && ty!=UCHAR && ty!=USHORT) { + return(fldal(ty)); + } + + for( i=0; i<=(SZINT-BTSHIFT-1); i+=TSHIFT ){ + switch( (ty>>i)&TMASK ){ + + case PTR: + return(ALPOINT); + case ARY: + continue; + case FTN: + cerror("compiler takes alignment of function"); + case 0: + break; + } + } + + + if ((al = attr_find(apl, GCC_ATYP_ALIGNED))) + return al->iarg(0); + al = attr_find(apl, ATTR_BASETYP); + if (al == NULL) + cerror("no basetyp"); + if (al->aalign == 0) + uerror("no alignment"); + return al->aalign; +} + +/* compute the size associated with type ty, + * dimoff d, and sizoff s */ +/* BETTER NOT BE CALLED WHEN t, d, and s REFER TO A BIT FIELD... */ +OFFSZ +tsize(TWORD ty, union dimfun *d, struct attr *apl) +{ + struct attr *ap; + OFFSZ mult, sz; + int i; + + mult = 1; + + for( i=0; i<=(SZINT-BTSHIFT-1); i+=TSHIFT ){ + switch( (ty>>i)&TMASK ){ + + case FTN: + uerror( "cannot take size of function"); + case PTR: + return( SZPOINT(ty) * mult ); + case ARY: + if (d->ddim == NOOFFSET) + return 0; + if (d->ddim < 0) + cerror("tsize: dynarray"); + mult *= d->ddim; + d++; + continue; + case 0: + break; + + } + } + + ap = attr_find(apl, ATTR_BASETYP); + sz = ap->atypsz; + +#ifdef GCC_COMPAT + if (ty == VOID) + sz = SZCHAR; +#endif + if (!ISSOU(BTYPE(ty))) { + if (sz == 0) { + uerror("unknown size"); + return(SZINT); + } + } else { + if (talign(ty, apl) == 0) + uerror("unknown structure/union/enum"); + } + + return((unsigned int)sz * mult); +} + +/* + * Save string (and print it out). If wide then wide string. + */ +NODE * +strend(int wide, char *str) +{ + struct symtab *sp; + NODE *p; + + /* If an identical string is already emitted, just forget this one */ + if (wide) { + /* Do not save wide strings, at least not now */ + sp = getsymtab(str, SSTRING|STEMP); + } else { + str = addstring(str); /* enter string in string table */ + sp = lookup(str, SSTRING); /* check for existance */ + } + + if (sp->soffset == 0) { /* No string */ + char *wr; + int i; + + sp->sclass = STATIC; + sp->slevel = 1; + sp->soffset = getlab(); + sp->squal = (CON >> TSHIFT); + sp->sdf = permalloc(sizeof(union dimfun)); + if (wide) { + sp->stype = WCHAR_TYPE+ARY; + sp->sap = MKAP(WCHAR_TYPE); + } else { + if (funsigned_char) { + sp->stype = UCHAR+ARY; + sp->sap = MKAP(UCHAR); + } else { + sp->stype = CHAR+ARY; + sp->sap = MKAP(CHAR); + } + } + for (wr = sp->sname, i = 1; *wr; i++) + if (*wr++ == '\\') + (void)esccon(&wr); + + sp->sdf->ddim = i; + if (wide) + inwstring(sp); + else + instring(sp); + } + + p = block(NAME, NIL, NIL, sp->stype, sp->sdf, sp->sap); + p->n_sp = sp; + return(clocal(p)); +} + +/* + * Print out a wide string by calling ninval(). + */ +void +inwstring(struct symtab *sp) +{ + char *s = sp->sname; + NODE *p; + + defloc(sp); + p = xbcon(0, NULL, WCHAR_TYPE); + do { + if (*s++ == '\\') + p->n_lval = esccon(&s); + else + p->n_lval = (unsigned char)s[-1]; + ninval(0, (MKAP(WCHAR_TYPE))->atypsz, p); + } while (s[-1] != 0); + nfree(p); +} + +/* + * update the offset pointed to by poff; return the + * offset of a value of size `size', alignment `alignment', + * given that off is increasing + */ +int +upoff(int size, int alignment, int *poff) +{ + int off; + + off = *poff; + SETOFF(off, alignment); + if (off < 0) + cerror("structure or stack overgrown"); /* wrapped */ + *poff = off+size; + return (off); +} + +/* + * allocate p with offset *poff, and update *poff + */ +int +oalloc(struct symtab *p, int *poff ) +{ + int al, off, tsz; + int noff; + + /* + * Only generate tempnodes if we are optimizing, + * and only for integers, floats or pointers, + * and not if the type on this level is volatile. + */ + if (xtemps && ((p->sclass == AUTO) || (p->sclass == REGISTER)) && + (p->stype < STRTY || ISPTR(p->stype)) && + !(cqual(p->stype, p->squal) & VOL) && cisreg(p->stype)) { + NODE *tn = tempnode(0, p->stype, p->sdf, p->sap); + p->soffset = regno(tn); + p->sflags |= STNODE; + nfree(tn); + return 0; + } + + al = talign(p->stype, p->sap); + noff = off = *poff; + tsz = (int)tsize(p->stype, p->sdf, p->sap); +#ifdef BACKAUTO + if (p->sclass == AUTO) { + noff = off + tsz; + if (noff < 0) + cerror("stack overflow"); + SETOFF(noff, al); + off = -noff; + } else +#endif + if (p->sclass == PARAM && (p->stype == CHAR || p->stype == UCHAR || + p->stype == SHORT || p->stype == USHORT || p->stype == BOOL)) { + off = upoff(SZINT, ALINT, &noff); +#ifndef RTOLBYTES + off = noff - tsz; +#endif + } else { + off = upoff(tsz, al, &noff); + } + + if (p->sclass != REGISTER) { + /* in case we are allocating stack space for register arguments */ + if (p->soffset == NOOFFSET) + p->soffset = off; + else if(off != p->soffset) + return(1); + } + + *poff = noff; + return(0); +} + +/* + * Delay emission of code generated in argument headers. + */ +static void +edelay(NODE *p) +{ + if (blevel == 1) { + /* Delay until after declarations */ + if (parlink == NULL) + parlink = p; + else + parlink = block(COMOP, parlink, p, 0, 0, 0); + } else + ecomp(p); +} + +/* + * Traverse through the array args, evaluate them and put the + * resulting temp numbers in the dim fields. + */ +static void +evalidx(struct symtab *sp) +{ + union dimfun *df; + NODE *p; + TWORD t; + int astkp = 0; + + if (arrstk[0] == NIL) + astkp++; /* for parameter arrays */ + + if (isdyn(sp)) + sp->sflags |= SDYNARRAY; + + df = sp->sdf; + for (t = sp->stype; t > BTMASK; t = DECREF(t)) { + if (!ISARY(t)) + continue; + if (df->ddim == -1) { + p = tempnode(0, INT, 0, MKAP(INT)); + df->ddim = -regno(p); + edelay(buildtree(ASSIGN, p, arrstk[astkp++])); + } + df++; + } + arrstkp = 0; +} + +/* + * Return 1 if dynamic array, 0 otherwise. + */ +int +isdyn(struct symtab *sp) +{ + union dimfun *df = sp->sdf; + TWORD t; + + for (t = sp->stype; t > BTMASK; t = DECREF(t)) { + if (!ISARY(t)) + return 0; + if (df->ddim < 0 && df->ddim != NOOFFSET) + return 1; + df++; + } + return 0; +} + +/* + * Allocate space on the stack for dynamic arrays (or at least keep track + * of the index). + * Strategy is as follows: + * - first entry is a pointer to the dynamic datatype. + * - if it's a one-dimensional array this will be the only entry used. + * - if it's a multi-dimensional array the following (numdim-1) integers + * will contain the sizes to multiply the indexes with. + * - code to write the dimension sizes this will be generated here. + * - code to allocate space on the stack will be generated here. + */ +static void +dynalloc(struct symtab *p, int *poff) +{ + union dimfun *df; + NODE *n, *tn, *pol; + TWORD t; + + /* + * The pointer to the array is not necessarily stored in a + * TEMP node, but if it is, its number is in the soffset field; + */ + t = p->stype; + p->sflags |= STNODE; + p->stype = INCREF(p->stype); /* Make this an indirect pointer */ + tn = tempnode(0, p->stype, p->sdf, p->sap); + p->soffset = regno(tn); + + df = p->sdf; + + pol = bcon(1); + for (; t > BTMASK; t = DECREF(t)) { + if (!ISARY(t)) + break; + if (df->ddim < 0) + n = tempnode(-df->ddim, INT, 0, MKAP(INT)); + else + n = bcon(df->ddim); + + pol = buildtree(MUL, pol, n); + df++; + } + /* Create stack gap */ + spalloc(tn, pol, tsize(t, 0, p->sap)); +} + +/* + * allocate a field of width w + * new is 0 if new entry, 1 if redefinition, -1 if alignment + */ +int +falloc(struct symtab *p, int w, NODE *pty) +{ + int al,sz,type; + + type = p ? p->stype : pty->n_type; + + if (type == BOOL) + type = BOOL_TYPE; + if (type < CHAR || type > ULONGLONG) { + uerror("illegal field type"); + type = INT; + } + + al = btattr[type].aalign; + sz = btattr[type].atypsz; + + if (w > sz) { + uerror("field too big"); + w = sz; + } + + if (w == 0) { /* align only */ + SETOFF(rpole->rstr, al); + if (p != NULL) + uerror("zero size field"); + return(0); + } + + if (rpole->rstr%al + w > sz) + SETOFF(rpole->rstr, al); + if (p == NULL) { + rpole->rstr += w; /* we know it will fit */ + return(0); + } + + /* establish the field */ + + p->soffset = rpole->rstr; + rpole->rstr += w; + p->stype = type; + fldty(p); + return(0); +} + +/* + * handle unitialized declarations assumed to be not functions: + * int a; + * extern int a; + * static int a; + */ +void +nidcl(NODE *p, int class) +{ + struct symtab *sp; + int commflag = 0; + + /* compute class */ + if (class == SNULL) { + if (blevel > 1) + class = AUTO; + else if (blevel != 0 || rpole) + cerror( "nidcl error" ); + else /* blevel = 0 */ + commflag = 1, class = EXTERN; + } + + defid(p, class); + +#ifdef GCC_COMPAT + if (p->n_op == CM) + cerror("nidcl CM"); +#endif + + sp = p->n_sp; + /* check if forward decl */ + if (ISARY(sp->stype) && sp->sdf->ddim == NOOFFSET) + return; + + if (sp->sflags & SASG) + return; /* already initialized */ + + switch (class) { + case EXTDEF: + /* simulate initialization by 0 */ + simpleinit(p->n_sp, bcon(0)); + break; + case EXTERN: + if (commflag) + lcommadd(p->n_sp); + else + extdec(p->n_sp); + break; + case STATIC: + if (blevel == 0) + lcommadd(p->n_sp); + else + defzero(p->n_sp); + break; + } +} + +struct lcd { + SLIST_ENTRY(lcd) next; + struct symtab *sp; +}; + +static SLIST_HEAD(, lcd) lhead = { NULL, &lhead.q_forw}; + +/* + * Add a local common statement to the printout list. + */ +void +lcommadd(struct symtab *sp) +{ + struct lcd *lc, *lcp; + + lcp = NULL; + SLIST_FOREACH(lc, &lhead, next) { + if (lc->sp == sp) + return; /* already exists */ + if (lc->sp == NULL && lcp == NULL) + lcp = lc; + } + if (lcp == NULL) { + lc = permalloc(sizeof(struct lcd)); + lc->sp = sp; + SLIST_INSERT_LAST(&lhead, lc, next); + } else + lcp->sp = sp; +} + +/* + * Delete a local common statement. + */ +void +lcommdel(struct symtab *sp) +{ + struct lcd *lc; + + SLIST_FOREACH(lc, &lhead, next) { + if (lc->sp == sp) { + lc->sp = NULL; + return; + } + } +} + +/* + * Print out the remaining common statements. + */ +void +lcommprint(void) +{ + struct lcd *lc; + + SLIST_FOREACH(lc, &lhead, next) { + if (lc->sp != NULL) + defzero(lc->sp); + } +} + +/* + * Merge given types to a single node. + * Any type can end up here. + * p is the old node, q is the old (if any). + * CLASS is AUTO, EXTERN, REGISTER, STATIC or TYPEDEF. + * QUALIFIER is VOL or CON + * TYPE is CHAR, SHORT, INT, LONG, SIGNED, UNSIGNED, VOID, BOOL, FLOAT, + * DOUBLE, STRTY, UNIONTY. + */ +struct typctx { + int class, qual, sig, uns, cmplx, imag, err; + TWORD type; + NODE *saved; + struct attr *pre, *post; +}; + +static void +typwalk(NODE *p, void *arg) +{ + struct typctx *tc = arg; + +#define cmop(x,y) block(CM, x, y, INT, 0, MKAP(INT)) + switch (p->n_op) { + case ATTRIB: + if (tc->saved && (tc->saved->n_qual & 1)) { + tc->post = attr_add(tc->post,gcc_attr_parse(p->n_left)); + } else { + tc->pre = attr_add(tc->pre, gcc_attr_parse(p->n_left)); + } + p->n_left = bcon(0); /* For tfree() */ + break; + case CLASS: + if (tc->class) + tc->err = 1; /* max 1 class */ + tc->class = p->n_type; + break; + + case QUALIFIER: +#if 0 + if (p->n_qual == 0) + uerror("invalid use of 'restrict'"); +#endif + tc->qual |= p->n_qual >> TSHIFT; + break; + + case TYPE: + if (p->n_sp != NULL || ISSOU(p->n_type)) { + /* typedef, enum or struct/union */ + if (tc->saved || tc->type) + tc->err = 1; +#ifdef GCC_COMPAT + if (ISSOU(p->n_type) && p->n_left) { + if (tc->post) + cerror("typwalk"); + tc->post = gcc_attr_parse(p->n_left); + } +#endif + tc->saved = ccopy(p); + break; + } + + switch (p->n_type) { + case BOOL: + case CHAR: + case FLOAT: + case VOID: + if (tc->type) + tc->err = 1; + tc->type = p->n_type; + break; + case DOUBLE: + if (tc->type == 0) + tc->type = DOUBLE; + else if (tc->type == LONG) + tc->type = LDOUBLE; + else + tc->err = 1; + break; + case SHORT: + if (tc->type == 0 || tc->type == INT) + tc->type = SHORT; + else + tc->err = 1; + break; + case INT: + if (tc->type == SHORT || tc->type == LONG || + tc->type == LONGLONG) + break; + else if (tc->type == 0) + tc->type = INT; + else + tc->err = 1; + break; + case LONG: + if (tc->type == 0) + tc->type = LONG; + else if (tc->type == INT) + break; + else if (tc->type == LONG) + tc->type = LONGLONG; + else if (tc->type == DOUBLE) + tc->type = LDOUBLE; + else + tc->err = 1; + break; + case SIGNED: + if (tc->sig || tc->uns) + tc->err = 1; + tc->sig = 1; + break; + case UNSIGNED: + if (tc->sig || tc->uns) + tc->err = 1; + tc->uns = 1; + break; + case COMPLEX: + tc->cmplx = 1; + break; + case IMAG: + tc->imag = 1; + break; + default: + cerror("typwalk"); + } + } + +} + +NODE * +typenode(NODE *p) +{ + struct symtab *sp; + struct typctx tc; + NODE *q; + char *c; + + memset(&tc, 0, sizeof(struct typctx)); + + flist(p, typwalk, &tc); + tfree(p); + + if (tc.err) + goto bad; + + if (tc.cmplx || tc.imag) { + if (tc.type == 0) + tc.type = DOUBLE; + if ((tc.cmplx && tc.imag) || tc.sig || tc.uns || + !ISFTY(tc.type)) + goto bad; + if (tc.cmplx) { + c = tc.type == DOUBLE ? "0d" : + tc.type == FLOAT ? "0f" : "0l"; + sp = lookup(addname(c), 0); + tc.type = STRTY; + tc.saved = mkty(tc.type, sp->sdf, sp->sap); + tc.saved->n_sp = sp; + tc.type = 0; + } else + tc.type += (FIMAG-FLOAT); + } + + if (tc.saved && tc.type) + goto bad; + if (tc.sig || tc.uns) { + if (tc.type == 0) + tc.type = tc.sig ? INT : UNSIGNED; + if (tc.type > ULONGLONG) + goto bad; + if (tc.uns) + tc.type = ENUNSIGN(tc.type); + } + + if (funsigned_char && tc.type == CHAR && tc.sig == 0) + tc.type = UCHAR; + +#ifdef GCC_COMPAT + if (pragma_packed) { + q = bdty(CALL, bdty(NAME, "packed"), bcon(pragma_packed)); + tc.post = attr_add(tc.post, gcc_attr_parse(q)); + } + if (pragma_aligned) { + /* Deal with relevant pragmas */ + q = bdty(CALL, bdty(NAME, "aligned"), bcon(pragma_aligned)); + tc.post = attr_add(tc.post, gcc_attr_parse(q)); + } + pragma_aligned = pragma_packed = 0; +#endif + if ((q = tc.saved) == NULL) { + TWORD t; + if ((t = BTYPE(tc.type)) > LDOUBLE && t != VOID && + t != BOOL && !(t >= FIMAG && t <= LIMAG)) + cerror("typenode2 t %x", tc.type); + if (t == UNDEF) { + t = INT; + MODTYPE(tc.type, INT); + } + q = mkty(tc.type, 0, MKAP(t)); + } + q->n_ap = attr_add(q->n_ap, tc.post); + q->n_qual = tc.qual; + q->n_lval = tc.class; +#ifdef GCC_COMPAT + if (tc.post) { + /* Can only occur for TYPEDEF, STRUCT or UNION */ + if (tc.saved == NULL) + cerror("typenode"); + } + if (tc.pre) + q->n_ap = attr_add(q->n_ap, tc.pre); + gcc_tcattrfix(q); +#endif + return q; + +bad: uerror("illegal type combination"); + return mkty(INT, 0, 0); +} + +struct tylnk { + struct tylnk *next; + union dimfun df; +}; + +static void tyreduce(NODE *p, struct tylnk **, int *); + +static void +tylkadd(union dimfun dim, struct tylnk **tylkp, int *ntdim) +{ + (*tylkp)->next = tmpalloc(sizeof(struct tylnk)); + *tylkp = (*tylkp)->next; + (*tylkp)->next = NULL; + (*tylkp)->df = dim; + (*ntdim)++; +} + +/* + * merge type typ with identifier idp. + * idp is returned as a NAME node with correct types, + * typ is untouched since multiple declarations uses it. + * typ has type attributes, idp can never carry such attributes + * so on return just a pointer to the typ attributes is returned. + */ +NODE * +tymerge(NODE *typ, NODE *idp) +{ + TWORD t; + NODE *p; + union dimfun *j; + struct tylnk *base, tylnk, *tylkp; + struct attr *ap, *bap; + int ntdim, i; + +#ifdef PCC_DEBUG + if (ddebug > 2) { + printf("tymerge(%p,%p)\n", typ, idp); + fwalk(typ, eprint, 0); + fwalk(idp, eprint, 0); + } +#endif + + if (typ->n_op == CM || idp->n_op == CM) + cerror("tymerge CM"); + + if (typ->n_op != TYPE) + cerror("tymerge: arg 1"); + + bap = typ->n_ap; + + idp->n_type = typ->n_type; + idp->n_qual |= typ->n_qual; + + tylkp = &tylnk; + tylkp->next = NULL; + ntdim = 0; + + tyreduce(idp, &tylkp, &ntdim); + + for (t = typ->n_type, j = typ->n_df; t&TMASK; t = DECREF(t)) + if (ISARY(t) || ISFTN(t)) + tylkadd(*j++, &tylkp, &ntdim); + + if (ntdim) { + union dimfun *a = permalloc(sizeof(union dimfun) * ntdim); + dimfuncnt += ntdim; + for (i = 0, base = tylnk.next; base; base = base->next, i++) + a[i] = base->df; + idp->n_df = a; + } else + idp->n_df = NULL; + + /* now idp is a single node: fix up type */ + if ((t = ctype(idp->n_type)) != idp->n_type) { + idp->n_type = t; + t = BTYPE(t); + if (bap->atype == ATTR_BASETYP) + bap = MKAP(t); + else { + for (ap = bap; + ap->next->atype != ATTR_BASETYP; ap = ap->next) + ; + ap->next = MKAP(t); + } + } + + if (idp->n_op != NAME) { + for (p = idp->n_left; p->n_op != NAME; p = p->n_left) + nfree(p); + nfree(p); + idp->n_op = NAME; + } + idp->n_ap = bap; + + return(idp); +} + +/* + * Retrieve all CM-separated argument types, sizes and dimensions and + * put them in an array. + * XXX - can only check first type level, side effects? + */ +static union arglist * +arglist(NODE *n) +{ + union arglist *al; + NODE *w = n, **ap; + int num, cnt, i, j, k; + TWORD ty; + +#ifdef PCC_DEBUG + if (pdebug) { + printf("arglist %p\n", n); + fwalk(n, eprint, 0); + } +#endif + /* First: how much to allocate */ + for (num = cnt = 0, w = n; w->n_op == CM; w = w->n_left) { + cnt++; /* Number of levels */ + num++; /* At least one per step */ + if (w->n_right->n_op == ELLIPSIS) + continue; + ty = w->n_right->n_type; + if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY) + num++; + while (ISFTN(ty) == 0 && ISARY(ty) == 0 && ty > BTMASK) + ty = DECREF(ty); + if (ty > BTMASK) + num++; + } + cnt++; + ty = w->n_type; + if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY) + num++; + while (ISFTN(ty) == 0 && ISARY(ty) == 0 && ty > BTMASK) + ty = DECREF(ty); + if (ty > BTMASK) + num++; + num += 2; /* TEND + last arg type */ + + /* Second: Create list to work on */ + ap = tmpalloc(sizeof(NODE *) * cnt); + al = permalloc(sizeof(union arglist) * num); + arglistcnt += num; + + for (w = n, i = 0; w->n_op == CM; w = w->n_left) + ap[i++] = w->n_right; + ap[i] = w; + + /* Third: Create actual arg list */ + for (k = 0, j = i; j >= 0; j--) { + if (ap[j]->n_op == ELLIPSIS) { + al[k++].type = TELLIPSIS; + ap[j]->n_op = ICON; /* for tfree() */ + continue; + } + /* Convert arrays to pointers */ + if (ISARY(ap[j]->n_type)) { + ap[j]->n_type += (PTR-ARY); + ap[j]->n_df++; + } + /* Convert (silently) functions to pointers */ + if (ISFTN(ap[j]->n_type)) + ap[j]->n_type = INCREF(ap[j]->n_type); + ty = ap[j]->n_type; +#ifdef GCC_COMPAT + if (ty == UNIONTY && + attr_find(ap[j]->n_ap, GCC_ATYP_TRANSP_UNION)){ + /* transparent unions must have compatible types + * shortcut here: if pointers, set void *, + * otherwise btype. + */ + struct symtab *sp = strmemb(ap[j]->n_ap); + ty = ISPTR(sp->stype) ? PTR|VOID : sp->stype; + } +#endif + al[k++].type = ty; + if (BTYPE(ty) == STRTY || BTYPE(ty) == UNIONTY) + al[k++].sap = ap[j]->n_ap; + while (ISFTN(ty) == 0 && ISARY(ty) == 0 && ty > BTMASK) + ty = DECREF(ty); + if (ty > BTMASK) + al[k++].df = ap[j]->n_df; + } + al[k++].type = TNULL; + if (k > num) + cerror("arglist: k%d > num%d", k, num); + tfree(n); +#ifdef PCC_DEBUG + if (pdebug) + alprint(al, 0); +#endif + return al; +} + +/* + * build a type, and stash away dimensions, + * from a parse tree of the declaration + * the type is build top down, the dimensions bottom up + */ +void +tyreduce(NODE *p, struct tylnk **tylkp, int *ntdim) +{ + union dimfun dim; + NODE *r = NULL; + int o; + TWORD t, q; + + o = p->n_op; + if (o == NAME) { + p->n_qual = DECQAL(p->n_qual); + return; + } + + t = INCREF(p->n_type); + q = p->n_qual; + switch (o) { + case CALL: + t += (FTN-PTR); + dim.dfun = arglist(p->n_right); + break; + case UCALL: + t += (FTN-PTR); + dim.dfun = NULL; + break; + case LB: + t += (ARY-PTR); + if (p->n_right->n_op != ICON) { + r = p->n_right; + o = RB; + } else { + dim.ddim = (int)p->n_right->n_lval; + nfree(p->n_right); +#ifdef notdef + /* XXX - check dimensions at usage time */ + if (dim.ddim == NOOFFSET && p->n_left->n_op == LB) + uerror("null dimension"); +#endif + } + break; + } + + p->n_left->n_type = t; + p->n_left->n_qual = INCQAL(q) | p->n_left->n_qual; + tyreduce(p->n_left, tylkp, ntdim); + + if (o == LB || o == (UCALL) || o == CALL) + tylkadd(dim, tylkp, ntdim); + if (o == RB) { + dim.ddim = -1; + tylkadd(dim, tylkp, ntdim); + arrstk[arrstkp++] = r; + } + + p->n_sp = p->n_left->n_sp; + p->n_type = p->n_left->n_type; + p->n_qual = p->n_left->n_qual; +} + +static NODE * +argcast(NODE *p, TWORD t, union dimfun *d, struct attr *ap) +{ + NODE *u, *r = talloc(); + + r->n_op = NAME; + r->n_type = t; + r->n_qual = 0; /* XXX */ + r->n_df = d; + r->n_ap = ap; + + u = buildtree(CAST, r, p); + nfree(u->n_left); + r = u->n_right; + nfree(u); + return r; +} + +#ifdef PCC_DEBUG +/* + * Print a prototype. + */ +static void +alprint(union arglist *al, int in) +{ + TWORD t; + int i = 0, j; + + for (; al->type != TNULL; al++) { + for (j = in; j > 0; j--) + printf(" "); + printf("arg %d: ", i++); + t = al->type; + tprint(stdout, t, 0); + while (t > BTMASK) { + if (ISARY(t)) { + al++; + printf(" dim %d ", al->df->ddim); + } else if (ISFTN(t)) { + al++; + alprint(al->df->dfun, in+1); + } + t = DECREF(t); + } + if (ISSOU(t)) { + al++; + struct attr *ap = attr_find(al->sap, ATTR_BASETYP); + printf(" (size %d align %d)", ap->atypsz, + ap->aalign); + } + printf("\n"); + } + if (in == 0) + printf("end arglist\n"); +} +#endif +int +suemeq(struct attr *s1, struct attr *s2) +{ + + return (strmemb(s1) == strmemb(s2)); +} + +/* + * Sanity-check old-style args. + */ +static NODE * +oldarg(NODE *p) +{ + if (p->n_op == TYPE) + uerror("type is not an argument"); + if (p->n_type == FLOAT) + return cast(p, DOUBLE, p->n_qual); + return p; +} + +/* + * Do prototype checking and add conversions before calling a function. + * Argument f is function and a is a CM-separated list of arguments. + * Returns a merged node (via buildtree() of function and arguments. + */ +NODE * +doacall(struct symtab *sp, NODE *f, NODE *a) +{ + NODE *w, *r; + union arglist *al; + struct ap { + struct ap *next; + NODE *node; + } *at, *apole = NULL; + int argidx/* , hasarray = 0*/; + TWORD type, arrt; + +#ifdef PCC_DEBUG + if (ddebug) { + printf("doacall.\n"); + fwalk(f, eprint, 0); + if (a) + fwalk(a, eprint, 0); + } +#endif + + /* First let MD code do something */ + calldec(f, a); +/* XXX XXX hack */ + if ((f->n_op == CALL) && + f->n_left->n_op == ADDROF && + f->n_left->n_left->n_op == NAME && + (f->n_left->n_left->n_type & 0x7e0) == 0x4c0) + goto build; +/* XXX XXX hack */ + +#ifndef NO_C_BUILTINS + /* check for builtins. function pointers are not allowed */ + if (f->n_op == NAME && + f->n_sp->sname[0] == '_' && f->n_sp->sname[1] == '_') + if ((w = builtin_check(f, a)) != NIL) + return w; +#endif + + /* Check for undefined or late defined enums */ + if (BTYPE(f->n_type) == ENUMTY) { + /* not-yet check if declared enum */ + struct symtab *sq = strmemb(f->n_ap); + if (sq->stype != ENUMTY) + MODTYPE(f->n_type, sq->stype); + if (BTYPE(f->n_type) == ENUMTY) + uerror("enum %s not declared", sq->sname); + } + + /* + * Do some basic checks. + */ + if (f->n_df == NULL || (al = f->n_df[0].dfun) == NULL) { + /* + * Handle non-prototype declarations. + */ + if (f->n_op == NAME && f->n_sp != NULL) { + if (strncmp(f->n_sp->sname, "__builtin", 9) != 0) + warner(Wmissing_prototypes, f->n_sp->sname); + } else + warner(Wmissing_prototypes, ""); + + /* floats must be cast to double */ + if (a == NULL) + goto build; + if (a->n_op != CM) { + a = oldarg(a); + } else { + for (w = a; w->n_left->n_op == CM; w = w->n_left) + w->n_right = oldarg(w->n_right); + w->n_left = oldarg(w->n_left); + w->n_right = oldarg(w->n_right); + } + goto build; + } + if (al->type == VOID) { + if (a != NULL) + uerror("function takes no arguments"); + goto build; /* void function */ + } else { + if (a == NULL) { + uerror("function needs arguments"); + goto build; + } + } +#ifdef PCC_DEBUG + if (pdebug) { + printf("arglist for %s\n", + f->n_sp != NULL ? f->n_sp->sname : "function pointer"); + alprint(al, 0); + } +#endif + + /* + * Create a list of pointers to the nodes given as arg. + */ + for (w = a; w->n_op == CM; w = w->n_left) { + at = tmpalloc(sizeof(struct ap)); + at->node = w->n_right; + at->next = apole; + apole = at; + } + at = tmpalloc(sizeof(struct ap)); + at->node = w; + at->next = apole; + apole = at; + + /* + * Do the typechecking by walking up the list. + */ + argidx = 1; + while (al->type != TNULL) { + if (al->type == TELLIPSIS) { + /* convert the rest of float to double */ + for (; apole; apole = apole->next) { + if (apole->node->n_type != FLOAT) + continue; + MKTY(apole->node, DOUBLE, 0, 0); + } + goto build; + } + if (apole == NULL) { + uerror("too few arguments to function"); + goto build; + } +/* al = prototyp, apole = argument till ftn */ +/* type = argumentets typ, arrt = prototypens typ */ + type = apole->node->n_type; + arrt = al->type; +#if 0 + if ((hasarray = ISARY(arrt))) + arrt += (PTR-ARY); +#endif + /* Taking addresses of arrays are meaningless in expressions */ + /* but people tend to do that and also use in prototypes */ + /* this is mostly a problem with typedefs */ + if (ISARY(type)) { + if (ISPTR(arrt) && ISARY(DECREF(arrt))) + type = INCREF(type); + else + type += (PTR-ARY); + } else if (ISPTR(type) && !ISARY(DECREF(type)) && + ISPTR(arrt) && ISARY(DECREF(arrt))) { + type += (ARY-PTR); + type = INCREF(type); + } + + /* Check structs */ + if (type <= BTMASK && arrt <= BTMASK) { + if (type != arrt) { + if (ISSOU(BTYPE(type)) || ISSOU(BTYPE(arrt))) { +incomp: uerror("incompatible types for arg %d", + argidx); + } else { + MKTY(apole->node, arrt, 0, 0) + } +#ifndef NO_COMPLEX + } else if (type == STRTY && + attr_find(apole->node->n_ap, ATTR_COMPLEX) && + attr_find(al[1].sap, ATTR_COMPLEX)) { + /* Both are complex */ + if (strmemb(apole->node->n_ap)->stype != + strmemb(al[1].sap)->stype) { + /* must convert to correct type */ + w = talloc(); + *w = *apole->node; + w = mkcmplx(w, + strmemb(al[1].sap)->stype); + *apole->node = *w; + nfree(w); + } + goto out; +#endif + } else if (ISSOU(BTYPE(type))) { + if (!suemeq(apole->node->n_ap, al[1].sap)) + goto incomp; + } + goto out; + } + + /* XXX should (recusively) check return type and arg list of + func ptr arg XXX */ + if (ISFTN(DECREF(arrt)) && ISFTN(type)) + type = INCREF(type); + + /* Hereafter its only pointers (or arrays) left */ + /* Check for struct/union intermixing with other types */ + if (((type <= BTMASK) && ISSOU(BTYPE(type))) || + ((arrt <= BTMASK) && ISSOU(BTYPE(arrt)))) + goto incomp; + + /* Check for struct/union compatibility */ + if (type == arrt) { + if (ISSOU(BTYPE(type))) { + if (suemeq(apole->node->n_ap, al[1].sap)) + goto out; + } else + goto out; + } + if (BTYPE(arrt) == VOID && type > BTMASK) + goto skip; /* void *f = some pointer */ + if (arrt > BTMASK && BTYPE(type) == VOID) + goto skip; /* some *f = void pointer */ + if (apole->node->n_op == ICON && apole->node->n_lval == 0) + goto skip; /* Anything assigned a zero */ + + if ((type & ~BTMASK) == (arrt & ~BTMASK)) { + /* do not complain for pointers with signedness */ + if ((DEUNSIGN(BTYPE(type)) == DEUNSIGN(BTYPE(arrt))) && + (BTYPE(type) != BTYPE(arrt))) { + warner(Wpointer_sign, NULL); + goto skip; + } + } + + werror("implicit conversion of argument %d due to prototype", + argidx); + +skip: if (ISSOU(BTYPE(arrt))) { + MKTY(apole->node, arrt, 0, al[1].sap) + } else { + MKTY(apole->node, arrt, 0, MKAP(BTYPE(arrt))) + } + +out: al++; + if (ISSOU(BTYPE(arrt))) + al++; +#if 0 + while (arrt > BTMASK && !ISFTN(arrt)) + arrt = DECREF(arrt); + if (ISFTN(arrt) || hasarray) + al++; +#else + while (arrt > BTMASK) { + if (ISARY(arrt) || ISFTN(arrt)) { + al++; + break; + } + arrt = DECREF(arrt); + } +#endif + apole = apole->next; + argidx++; + } + if (apole != NULL) + uerror("too many arguments to function"); + +build: if (sp != NULL && (sp->sflags & SINLINE) && (w = inlinetree(sp, f, a))) + return w; + return buildtree(a == NIL ? UCALL : CALL, f, a); +} + +static int +chk2(TWORD type, union dimfun *dsym, union dimfun *ddef) +{ + while (type > BTMASK) { + switch (type & TMASK) { + case ARY: + /* may be declared without dimension */ + if (dsym->ddim == NOOFFSET) + dsym->ddim = ddef->ddim; + if (dsym->ddim < 0 && ddef->ddim < 0) + ; /* dynamic arrays as arguments */ + else if (ddef->ddim > 0 && dsym->ddim != ddef->ddim) + return 1; + dsym++, ddef++; + break; + case FTN: + /* old-style function headers with function pointers + * will most likely not have a prototype. + * This is not considered an error. */ + if (ddef->dfun == NULL) { +#ifdef notyet + werror("declaration not a prototype"); +#endif + } else if (chkftn(dsym->dfun, ddef->dfun)) + return 1; + dsym++, ddef++; + break; + } + type = DECREF(type); + } + return 0; +} + +/* + * Compare two function argument lists to see if they match. + */ +int +chkftn(union arglist *usym, union arglist *udef) +{ + TWORD t2; + int ty, tyn; + + if (usym == NULL) + return 0; + if (cftnsp != NULL && udef == NULL && usym->type == VOID) + return 0; /* foo() { function with foo(void); prototype */ + if (udef == NULL && usym->type != TNULL) + return 1; + while (usym->type != TNULL) { + if (usym->type == udef->type) + goto done; + /* + * If an old-style declaration, then all types smaller than + * int are given as int parameters. + */ + if (intcompare) { + ty = BTYPE(usym->type); + tyn = BTYPE(udef->type); + if (ty == tyn || ty != INT) + return 1; + if (tyn == CHAR || tyn == UCHAR || + tyn == SHORT || tyn == USHORT) + goto done; + return 1; + } else + return 1; + +done: ty = BTYPE(usym->type); + t2 = usym->type; + if (ISSOU(ty)) { + usym++, udef++; + if (suemeq(usym->sap, udef->sap) == 0) + return 1; + } + + while (ISFTN(t2) == 0 && ISARY(t2) == 0 && t2 > BTMASK) + t2 = DECREF(t2); + if (t2 > BTMASK) { + usym++, udef++; + if (chk2(t2, usym->df, udef->df)) + return 1; + } + usym++, udef++; + } + if (usym->type != udef->type) + return 1; + return 0; +} + +void +fixtype(NODE *p, int class) +{ + unsigned int t, type; + int mod1, mod2; + /* fix up the types, and check for legality */ + + /* forward declared enums */ + if (BTYPE(p->n_sp->stype) == ENUMTY) { + MODTYPE(p->n_sp->stype, strmemb(p->n_sp->sap)->stype); + } + + if( (type = p->n_type) == UNDEF ) return; + if ((mod2 = (type&TMASK))) { + t = DECREF(type); + while( mod1=mod2, mod2 = (t&TMASK) ){ + if( mod1 == ARY && mod2 == FTN ){ + uerror( "array of functions is illegal" ); + type = 0; + } + else if( mod1 == FTN && ( mod2 == ARY || mod2 == FTN ) ){ + uerror( "function returns illegal type" ); + type = 0; + } + t = DECREF(t); + } + } + + /* detect function arguments, watching out for structure declarations */ + if (rpole && ISFTN(type)) { + uerror("function illegal in structure or union"); + type = INCREF(type); + } + p->n_type = type; +} + +/* + * give undefined version of class + */ +int +uclass(int class) +{ + if (class == SNULL) + return(EXTERN); + else if (class == STATIC) + return(USTATIC); + else + return(class); +} + +int +fixclass(int class, TWORD type) +{ + extern int fun_inline; + + /* first, fix null class */ + if (class == SNULL) { + if (fun_inline && ISFTN(type)) + return SNULL; + if (rpole) + class = rpole->rsou == STNAME ? MOS : MOU; + else if (blevel == 0) + class = EXTDEF; + else + class = AUTO; + } + + /* now, do general checking */ + + if( ISFTN( type ) ){ + switch( class ) { + default: + uerror( "function has illegal storage class" ); + case AUTO: + class = EXTERN; + case EXTERN: + case EXTDEF: + case TYPEDEF: + case STATIC: + case USTATIC: + ; + } + } + + if (class & FIELD) { + if (rpole && rpole->rsou != STNAME && rpole->rsou != UNAME) + uerror("illegal use of field"); + return(class); + } + + switch (class) { + + case MOS: + case MOU: + if (rpole == NULL) + uerror("illegal member class"); + return(class); + + case REGISTER: + if (blevel == 0) + uerror("illegal register declaration"); + if (blevel == 1) + return(PARAM); + else + return(AUTO); + + case AUTO: + if( blevel < 2 ) uerror( "illegal ULABEL class" ); + return( class ); + + case EXTERN: + case STATIC: + case EXTDEF: + case TYPEDEF: + case USTATIC: + case PARAM: + return( class ); + + default: + cerror( "illegal class: %d", class ); + /* NOTREACHED */ + + } + return 0; /* XXX */ +} + +/* + * Generates a goto statement; sets up label number etc. + */ +void +gotolabel(char *name) +{ + struct symtab *s = lookup(name, SLBLNAME); + + if (s->soffset == 0) + s->soffset = -getlab(); + branch(s->soffset < 0 ? -s->soffset : s->soffset); +} + +/* + * Sets a label for gotos. + */ +void +deflabel(char *name, NODE *p) +{ + struct symtab *s = lookup(name, SLBLNAME); + + s->sap = gcc_attr_parse(p); + if (s->soffset > 0) + uerror("label '%s' redefined", name); + if (s->soffset == 0) + s->soffset = getlab(); + if (s->soffset < 0) + s->soffset = -s->soffset; + plabel( s->soffset); +} + +struct symtab * +getsymtab(char *name, int flags) +{ + struct symtab *s; + + if (flags & STEMP) { + s = tmpalloc(sizeof(struct symtab)); + } else { + s = permalloc(sizeof(struct symtab)); + symtabcnt++; + } + s->sname = name; + s->soname = NULL; + s->snext = NULL; + s->stype = UNDEF; + s->squal = 0; + s->sclass = SNULL; + s->sflags = (short)(flags & SMASK); + s->soffset = 0; + s->slevel = (char)blevel; + s->sdf = NULL; + s->sap = NULL; + return s; +} + +int +fldchk(int sz) +{ + if (rpole->rsou != STNAME && rpole->rsou != UNAME) + uerror("field outside of structure"); + if (sz < 0 || sz >= FIELD) { + uerror("illegal field size"); + return 1; + } + return 0; +} + +#ifdef PCC_DEBUG +static char * +ccnames[] = { /* names of storage classes */ + "SNULL", + "AUTO", + "EXTERN", + "STATIC", + "REGISTER", + "EXTDEF", + "LABEL", + "ULABEL", + "MOS", + "PARAM", + "STNAME", + "MOU", + "UNAME", + "TYPEDEF", + "FORTRAN", + "ENAME", + "MOE", + "UFORTRAN", + "USTATIC", + }; + +char * +scnames(int c) +{ + /* return the name for storage class c */ + static char buf[12]; + if( c&FIELD ){ + snprintf( buf, sizeof(buf), "FIELD[%d]", c&FLDSIZ ); + return( buf ); + } + return( ccnames[c] ); + } +#endif + +static char *stack_chk_fail = "__stack_chk_fail"; +static char *stack_chk_guard = "__stack_chk_guard"; +static char *stack_chk_canary = "__stack_chk_canary"; + +void +sspinit() +{ + NODE *p; + + p = block(NAME, NIL, NIL, FTN+VOID, 0, MKAP(VOID)); + p->n_sp = lookup(stack_chk_fail, SNORMAL); + defid(p, EXTERN); + nfree(p); + + p = block(NAME, NIL, NIL, INT, 0, MKAP(INT)); + p->n_sp = lookup(stack_chk_guard, SNORMAL); + defid(p, EXTERN); + nfree(p); +} + +void +sspstart() +{ + NODE *p, *q; + + q = block(NAME, NIL, NIL, INT, 0, MKAP(INT)); + q->n_sp = lookup(stack_chk_guard, SNORMAL); + q = clocal(q); + + p = block(REG, NIL, NIL, INT, 0, 0); + p->n_lval = 0; + p->n_rval = FPREG; + q = block(ER, p, q, INT, 0, MKAP(INT)); + q = clocal(q); + + p = block(NAME, NIL, NIL, INT, 0, MKAP(INT)); + p->n_qual = VOL >> TSHIFT; + p->n_sp = lookup(stack_chk_canary, SNORMAL); + defid(p, AUTO); + p = clocal(p); + ecomp(buildtree(ASSIGN, p, q)); +} + +void +sspend() +{ + NODE *p, *q; + TWORD t; + int lab; + + if (retlab != NOLAB) { + plabel(retlab); + retlab = getlab(); + } + + t = DECREF(cftnsp->stype); + if (t == BOOL) + t = BOOL_TYPE; + + p = block(NAME, NIL, NIL, INT, 0, MKAP(INT)); + p->n_sp = lookup(stack_chk_canary, SNORMAL); + p = clocal(p); + + q = block(REG, NIL, NIL, INT, 0, 0); + q->n_lval = 0; + q->n_rval = FPREG; + q = block(ER, p, q, INT, 0, MKAP(INT)); + + p = block(NAME, NIL, NIL, INT, 0, MKAP(INT)); + p->n_sp = lookup(stack_chk_guard, SNORMAL); + p = clocal(p); + + lab = getlab(); + cbranch(buildtree(EQ, p, q), bcon(lab)); + + p = block(NAME, NIL, NIL, FTN+VOID, 0, MKAP(VOID)); + p->n_sp = lookup(stack_chk_fail, SNORMAL); + p = clocal(p); + + ecomp(buildtree(UCALL, p, NIL)); + + plabel(lab); +} + +/* + * Allocate on the permanent heap for inlines, otherwise temporary heap. + */ +void * +blkalloc(int size) +{ + return isinlining || blevel < 2 ? permalloc(size) : tmpalloc(size); +} + +/* + * Allocate on the permanent heap for inlines, otherwise temporary heap. + */ +void * +inlalloc(int size) +{ + return isinlining ? permalloc(size) : tmpalloc(size); +} + +struct attr * +attr_new(int type, int nelem) +{ + struct attr *ap; + int sz; + + sz = sizeof(struct attr) + nelem * sizeof(union aarg); + + ap = memset(blkalloc(sz), 0, sz); + ap->atype = type; + return ap; +} + +/* + * Add attribute list new before old and return new. + */ +struct attr * +attr_add(struct attr *old, struct attr *new) +{ + struct attr *ap; + + if (new == NULL) + return old; /* nothing to add */ + + for (ap = new; ap->next; ap = ap->next) + ; + ap->next = old; + return new; +} + +/* + * Search for attribute type in list ap. Return entry or NULL. + */ +struct attr * +attr_find(struct attr *ap, int type) +{ + + for (; ap && ap->atype != type; ap = ap->next) + ; + return ap; +} + +/* + * Copy an attribute struct. + * Return destination. + */ +struct attr * +attr_copy(struct attr *aps, struct attr *apd, int n) +{ + int sz = sizeof(struct attr) + n * sizeof(union aarg); + return memcpy(apd, aps, sz); +} + +/* + * Duplicate an attribute, like strdup. + */ +struct attr * +attr_dup(struct attr *ap, int n) +{ + int sz = sizeof(struct attr) + n * sizeof(union aarg); + ap = memcpy(blkalloc(sz), ap, sz); + ap->next = NULL; + return ap; +} + +/* + * Fetch pointer to first member in a struct list. + */ +struct symtab * +strmemb(struct attr *ap) +{ + + if ((ap = attr_find(ap, ATTR_STRUCT)) == NULL) + cerror("strmemb"); + return ap->amlist; +} + +#ifndef NO_COMPLEX + +static char *real, *imag; +static struct symtab *cxsp[3]; +/* + * As complex numbers internally are handled as structs, create + * these by hand-crafting them. + */ +void +complinit() +{ + struct attr *ap; + struct rstack *rp; + NODE *p, *q; + char *n[] = { "0f", "0d", "0l" }; + int i, odebug; + + odebug = ddebug; + ddebug = 0; + real = addname("__real"); + imag = addname("__imag"); + p = block(NAME, NIL, NIL, FLOAT, 0, MKAP(FLOAT)); + for (i = 0; i < 3; i++) { + p->n_type = FLOAT+i; + p->n_ap = MKAP(FLOAT+i); + rpole = rp = bstruct(NULL, STNAME, NULL); + soumemb(p, real, 0); + soumemb(p, imag, 0); + q = dclstruct(rp); + cxsp[i] = q->n_sp = lookup(addname(n[i]), 0); + defid(q, TYPEDEF); + ap = attr_new(ATTR_COMPLEX, 0); + q->n_sp->sap = attr_add(q->n_sp->sap, ap); + nfree(q); + } + nfree(p); + ddebug = odebug; +} + +/* + * Return the highest real floating point type. + * Known that at least one type is complex or imaginary. + */ +static TWORD +maxtyp(NODE *l, NODE *r) +{ + TWORD tl, tr, t; + + tl = ANYCX(l) ? strmemb(l->n_ap)->stype : l->n_type; + tr = ANYCX(r) ? strmemb(r->n_ap)->stype : r->n_type; + if (ISITY(tl)) + tl -= (FIMAG - FLOAT); + if (ISITY(tr)) + tr -= (FIMAG - FLOAT); + t = tl > tr ? tl : tr; + if (!ISFTY(t)) + cerror("maxtyp"); + return t; +} + +/* + * Fetch space on stack for complex struct. + */ +static NODE * +cxstore(TWORD t) +{ + struct symtab s; + + s = *cxsp[t - FLOAT]; + s.sclass = AUTO; + s.soffset = NOOFFSET; + oalloc(&s, &autooff); + return nametree(&s); +} + +#define comop(x,y) buildtree(COMOP, x, y) + +static NODE * +mkcmplx(NODE *p, TWORD dt) +{ + NODE *q, *r, *i, *t; + + if (!ANYCX(p)) { + /* Not complex, convert to complex on stack */ + q = cxstore(dt); + if (ISITY(p->n_type)) { + p->n_type = p->n_type - FIMAG + FLOAT; + r = bcon(0); + i = p; + } else { + r = p; + i = bcon(0); + } + p = buildtree(ASSIGN, structref(ccopy(q), DOT, real), r); + p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, imag), i)); + p = comop(p, q); + } else { + if (strmemb(p->n_ap)->stype != dt) { + q = cxstore(dt); + p = buildtree(ADDROF, p, NIL); + t = tempnode(0, p->n_type, p->n_df, p->n_ap); + p = buildtree(ASSIGN, ccopy(t), p); + p = comop(p, buildtree(ASSIGN, + structref(ccopy(q), DOT, real), + structref(ccopy(t), STREF, real))); + p = comop(p, buildtree(ASSIGN, + structref(ccopy(q), DOT, imag), + structref(t, STREF, imag))); + p = comop(p, q); + } + } + return p; +} + +static NODE * +cxasg(NODE *l, NODE *r) +{ + TWORD tl, tr; + + tl = strattr(l->n_ap) ? strmemb(l->n_ap)->stype : 0; + tr = strattr(r->n_ap) ? strmemb(r->n_ap)->stype : 0; + + if (ANYCX(l) && ANYCX(r) && tl != tr) { + /* different types in structs */ + r = mkcmplx(r, tl); + } else if (!ANYCX(l)) + r = structref(r, DOT, ISITY(l->n_type) ? imag : real); + else if (!ANYCX(r)) + r = mkcmplx(r, tl); + return buildtree(ASSIGN, l, r); +} + +/* + * Fixup complex operations. + * At least one operand is complex. + */ +NODE * +cxop(int op, NODE *l, NODE *r) +{ + TWORD mxtyp; + NODE *p, *q; + NODE *ltemp, *rtemp; + NODE *real_l, *imag_l; + NODE *real_r, *imag_r; + + if (op == ASSIGN) + return cxasg(l, r); + + mxtyp = maxtyp(l, r); + l = mkcmplx(l, mxtyp); + r = mkcmplx(r, mxtyp); + + + /* put a pointer to left and right elements in a TEMP */ + l = buildtree(ADDROF, l, NIL); + ltemp = tempnode(0, l->n_type, l->n_df, l->n_ap); + l = buildtree(ASSIGN, ccopy(ltemp), l); + + r = buildtree(ADDROF, r, NIL); + rtemp = tempnode(0, r->n_type, r->n_df, r->n_ap); + r = buildtree(ASSIGN, ccopy(rtemp), r); + + p = comop(l, r); + + /* create the four trees needed for calculation */ + real_l = structref(ccopy(ltemp), STREF, real); + real_r = structref(ccopy(rtemp), STREF, real); + imag_l = structref(ltemp, STREF, imag); + imag_r = structref(rtemp, STREF, imag); + + /* get storage on stack for the result */ + q = cxstore(mxtyp); + + switch (op) { + case NE: + case EQ: + tfree(q); + p = buildtree(op, comop(p, real_l), real_r); + q = buildtree(op, imag_l, imag_r); + p = buildtree(op == EQ ? ANDAND : OROR, p, q); + return p; + + case PLUS: + case MINUS: + p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, real), + buildtree(op, real_l, real_r))); + p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, imag), + buildtree(op, imag_l, imag_r))); + break; + + case MUL: + /* Complex mul is "complex" */ + /* (u+iv)*(x+iy)=((u*x)-(v*y))+i(v*x+y*u) */ + p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, real), + buildtree(MINUS, + buildtree(MUL, ccopy(real_r), ccopy(real_l)), + buildtree(MUL, ccopy(imag_r), ccopy(imag_l))))); + p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, imag), + buildtree(PLUS, + buildtree(MUL, real_r, imag_l), + buildtree(MUL, imag_r, real_l)))); + break; + + case DIV: + /* Complex div is even more "complex" */ + /* (u+iv)/(x+iy)=(u*x+v*y)/(x*x+y*y)+i((v*x-u*y)/(x*x+y*y)) */ + p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, real), + buildtree(DIV, + buildtree(PLUS, + buildtree(MUL, ccopy(real_r), ccopy(real_l)), + buildtree(MUL, ccopy(imag_r), ccopy(imag_l))), + buildtree(PLUS, + buildtree(MUL, ccopy(real_r), ccopy(real_r)), + buildtree(MUL, ccopy(imag_r), ccopy(imag_r)))))); + p = comop(p, buildtree(ASSIGN, structref(ccopy(q), DOT, real), + buildtree(DIV, + buildtree(MINUS, + buildtree(MUL, ccopy(imag_l), ccopy(real_r)), + buildtree(MUL, ccopy(real_l), ccopy(imag_r))), + buildtree(PLUS, + buildtree(MUL, ccopy(real_r), ccopy(real_r)), + buildtree(MUL, ccopy(imag_r), ccopy(imag_r)))))); + tfree(real_r); + tfree(real_l); + tfree(imag_r); + tfree(imag_l); + break; + default: + cerror("bad complex op %d", op); + } + return comop(p, q); +} + +/* + * Fixup imaginary operations. + * At least one operand is imaginary, none is complex. + */ +NODE * +imop(int op, NODE *l, NODE *r) +{ + NODE *p, *q; + TWORD mxtyp; + int li, ri; + + li = ri = 0; + if (ISITY(l->n_type)) + li = 1, l->n_type = l->n_type - (FIMAG-FLOAT); + if (ISITY(r->n_type)) + ri = 1, r->n_type = r->n_type - (FIMAG-FLOAT); + + mxtyp = maxtyp(l, r); + switch (op) { + case ASSIGN: + /* if both are imag, store value, otherwise store 0.0 */ + if (!(li && ri)) { + tfree(r); + r = bcon(0); + } + p = buildtree(ASSIGN, l, r); + p->n_type = p->n_type += (FIMAG-FLOAT); + break; + + case PLUS: + if (li && ri) { + p = buildtree(PLUS, l, r); + p->n_type = p->n_type += (FIMAG-FLOAT); + } else { + /* If one is imaginary and one is real, make complex */ + if (li) + q = l, l = r, r = q; /* switch */ + q = cxstore(mxtyp); + p = buildtree(ASSIGN, + structref(ccopy(q), DOT, real), l); + p = comop(p, buildtree(ASSIGN, + structref(ccopy(q), DOT, imag), r)); + p = comop(p, q); + } + break; + + case MINUS: + if (li && ri) { + p = buildtree(MINUS, l, r); + p->n_type = p->n_type += (FIMAG-FLOAT); + } else if (li) { + q = cxstore(mxtyp); + p = buildtree(ASSIGN, structref(ccopy(q), DOT, real), + buildtree(UMINUS, r, NIL)); + p = comop(p, buildtree(ASSIGN, + structref(ccopy(q), DOT, imag), l)); + p = comop(p, q); + } else /* if (ri) */ { + q = cxstore(mxtyp); + p = buildtree(ASSIGN, + structref(ccopy(q), DOT, real), l); + p = comop(p, buildtree(ASSIGN, + structref(ccopy(q), DOT, imag), + buildtree(UMINUS, r, NIL))); + p = comop(p, q); + } + break; + + case MUL: + p = buildtree(MUL, l, r); + if (li && ri) + p = buildtree(UMINUS, p, NIL); + if (li ^ ri) + p->n_type = p->n_type += (FIMAG-FLOAT); + break; + + case DIV: + p = buildtree(DIV, l, r); + if (ri && !li) + p = buildtree(UMINUS, p, NIL); + if (li ^ ri) + p->n_type = p->n_type += (FIMAG-FLOAT); + break; + default: + cerror("imop"); + p = NULL; + } + return p; +} + +NODE * +cxelem(int op, NODE *p) +{ + + if (ANYCX(p)) { + p = structref(p, DOT, op == XREAL ? real : imag); + } else if (op == XIMAG) { + /* XXX sanitycheck? */ + tfree(p); + p = bcon(0); + } + return p; +} + +NODE * +cxconj(NODE *p) +{ + NODE *q, *r; + + /* XXX side effects? */ + q = cxstore(strmemb(p->n_ap)->stype); + r = buildtree(ASSIGN, structref(ccopy(q), DOT, real), + structref(ccopy(p), DOT, real)); + r = comop(r, buildtree(ASSIGN, structref(ccopy(q), DOT, imag), + buildtree(UMINUS, structref(p, DOT, imag), NIL))); + return comop(r, q); +} + +/* + * Prepare for return. + * There may be implicit casts to other types. + */ +NODE * +cxret(NODE *p, NODE *q) +{ +//printf("cxret\n"); +//fwalk(p, eprint, 0); + if (ANYCX(q)) { /* Return complex type */ + p = mkcmplx(p, strmemb(q->n_ap)->stype); + } else if (ISFTY(q->n_type) || ISITY(q->n_type)) { /* real or imag */ + p = structref(p, DOT, ISFTY(q->n_type) ? real : imag); + if (p->n_type != q->n_type) + p = cast(p, q->n_type, 0); + } else + cerror("cxred failing type"); + return p; +} +#endif diff --git a/compilers/pcc/pcc-1.0.0/cc/ccom/scan.l b/compilers/pcc/pcc-1.0.0/cc/ccom/scan.l new file mode 100644 index 00000000..95a94689 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/ccom/scan.l @@ -0,0 +1,773 @@ +%{ +/* $Id: scan.l,v 1.102 2011/02/16 18:50:42 ragge Exp $ */ + +/* + * Copyright (c) 2002 Anders Magnusson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +%} + + +D [0-9] +L [a-zA-Z_] +H [a-fA-F0-9] +E [Ee][+-]?{D}+ +P [Pp][+-]?{D}+ +FS (f|F|l|L)?i? +IS (u|U|l|L)* +UL ({L}|\\u{H}{H}{H}{H}|\\U{H}{H}{H}{H}{H}{H}{H}{H}) + +%{ +#include +#include +#include +#include +#include + +#include "pass1.h" +#include "cgram.h" + +static NODE *cvtdig(int radix); +static NODE *charcon(void); +static NODE *wcharcon(void); +static void control(int); +static void pragma(void); +int notype, parbal, inattr, parlvl; +static int resw(TWORD, int); + +#define CPP_IDENT 2 +#define CPP_LINE 3 +#define CPP_HASH 4 + +#ifdef STABS +#define STABS_LINE(x) if (gflag && cftnsp) stabs_line(x) +#else +#define STABS_LINE(x) +#endif +#if defined(FLEX_SCANNER) && YY_FLEX_SUBMINOR_VERSION == 31 +/* Hack to avoid unnecessary warnings */ +FILE *yyget_in (void); +FILE *yyget_out (void); +int yyget_leng (void); +char *yyget_text (void); +void yyset_in (FILE *); +void yyset_out (FILE *); +int yyget_debug (void); +void yyset_debug (int); +int yylex_destroy (void); +extern int yyget_lineno (void); +extern void yyset_lineno (int); +#endif + +%} + +%% + +"__func__" { + if (cftnsp == NULL) + uerror("__func__ outside function"); + yylval.strp = cftnsp->sname; /* XXX - not C99 */ + return(C_STRING); + } +"asm" { return(C_ASM); } +"auto" { return resw(AUTO, C_CLASS); } +"_Bool" { return resw(BOOL, C_TYPE); } +"break" { return(C_BREAK); } +"case" { return(C_CASE); } +"char" { return resw(CHAR, C_TYPE); } +"_Complex" { return resw(COMPLEX, C_TYPE); } +"const" { return resw(CON, C_QUALIFIER); } +"continue" { return(C_CONTINUE); } +"default" { return(C_DEFAULT); } +"do" { return(C_DO); } +"double" { return resw(DOUBLE, C_TYPE); } +"else" { return(C_ELSE); } +"enum" { notype=1; return(C_ENUM); } +"extern" { return resw(EXTERN, C_CLASS); } +"float" { return resw(FLOAT, C_TYPE); } +"for" { return(C_FOR); } +"goto" { notype=1; return(C_GOTO); } +"if" { return(C_IF); } +"_Imaginary" { return resw(IMAG, C_TYPE); } +"inline" { return(C_FUNSPEC); } +"int" { return resw(INT, C_TYPE); } +"long" { return resw(LONG, C_TYPE); } +"register" { return resw(REGISTER, C_CLASS); } +"restrict" { ; /* just ignore */ } +"return" { return(C_RETURN); } +"short" { return resw(SHORT, C_TYPE); } +"signed" { return resw(SIGNED, C_TYPE); } +"sizeof" { return(C_SIZEOF); } +"static" { return resw(STATIC, C_CLASS); } +"struct" { yylval.intval = STNAME; notype=1; return(C_STRUCT); } +"switch" { return(C_SWITCH); } +"typedef" { return resw(TYPEDEF, C_CLASS); } +"union" { yylval.intval = UNAME; notype=1; return(C_STRUCT); } +"unsigned" { return resw(UNSIGNED, C_TYPE); } +"void" { return resw(VOID, C_TYPE); } +"volatile" { return resw(VOL, C_QUALIFIER); } +"while" { return(C_WHILE); } + +{UL}({UL}|{D})* { struct symtab *s; + int i = 0; + + yylval.strp = addname(yytext); +#ifdef GCC_COMPAT + if ((i = gcc_keyword(yylval.strp, &yylval.nodep)) > 0) + return i; +#endif + if (i == 0) { + if (notype) + return(C_NAME); + s = lookup(yylval.strp, SNOCREAT); + return s && s->sclass == TYPEDEF ? + notype=1, C_TYPENAME : C_NAME; + } + } + +0[xX]{H}+{IS}? { yylval.nodep = cvtdig(16); return(C_ICON); } +0{D}+{IS}? { yylval.nodep = cvtdig(8); return(C_ICON); } +{D}+{IS}? { yylval.nodep = cvtdig(10); return(C_ICON); } +L'(\\.|[^\\'])+' { yylval.nodep = wcharcon(); return(C_ICON); } +'(\\.|[^\\'])+' { yylval.nodep = charcon(); return(C_ICON); } + +{D}+{E}{FS}? { yylval.nodep = floatcon(yytext); return(C_FCON); } +{D}*"."{D}+({E})?{FS}? { yylval.nodep = floatcon(yytext); return(C_FCON); } +{D}+"."{D}*({E})?{FS}? { yylval.nodep = floatcon(yytext); return(C_FCON); } +0[xX]{H}*"."{H}+{P}{FS}? { yylval.nodep = fhexcon(yytext); return(C_FCON); } +0[xX]{H}+"."{P}{FS}? { yylval.nodep = fhexcon(yytext); return(C_FCON); } +0[xX]{H}+{P}{FS}? { yylval.nodep = fhexcon(yytext); return(C_FCON); } + +L?\"(\\.|[^\\"])*\" { yylval.strp = yytext; return C_STRING; } + +"..." { return(C_ELLIPSIS); } +">>=" { yylval.intval = RSEQ; return(C_ASOP); } +"<<=" { yylval.intval = LSEQ; return(C_ASOP); } +"+=" { yylval.intval = PLUSEQ; return(C_ASOP); } +"-=" { yylval.intval = MINUSEQ; return(C_ASOP); } +"*=" { yylval.intval = MULEQ; return(C_ASOP); } +"/=" { yylval.intval = DIVEQ; return(C_ASOP); } +"%=" { yylval.intval = MODEQ; return(C_ASOP); } +"&=" { yylval.intval = ANDEQ; return(C_ASOP); } +"^=" { yylval.intval = EREQ; return(C_ASOP); } +"|=" { yylval.intval = OREQ; return(C_ASOP); } +">>" { yylval.intval = RS; return(C_SHIFTOP); } +"<<" { yylval.intval = LS; return(C_SHIFTOP); } +"++" { yylval.intval = INCR; return(C_INCOP); } +"--" { yylval.intval = DECR; return(C_INCOP); } +"->" { yylval.intval = STREF; return(C_STROP); } +"&&" { yylval.intval = ANDAND; return(C_ANDAND); } +"||" { yylval.intval = OROR; return(C_OROR); } +"<=" { yylval.intval = LE; return(C_RELOP); } +">=" { yylval.intval = GE; return(C_RELOP); } +"==" { yylval.intval = EQ; return(C_EQUOP); } +"!=" { yylval.intval = NE; return(C_EQUOP); } +";" { notype = 0; return(';'); } +("{"|"<%") { notype = 0; return('{'); } +("}"|"%>") { if (rpole) notype = 1; return('}'); } +"," { if (parbal) notype = 0; return(','); } +":" { return(':'); } +"=" { return('='); } +"(" { parbal++; notype = 0; return('('); } +")" { parbal--; + if (parbal==0) { notype = 0; } + if (inattr && parlvl == parbal) + inattr = 0; + return(')'); } +("["|"<:") { return('['); } +("]"|":>") { return(']'); } +"." { yylval.intval = DOT; return(C_STROP); } +"&" { return('&'); } +"!" { yylval.intval = NOT; return(C_UNOP); } +"~" { yylval.intval = COMPL; return(C_UNOP); } +"-" { return('-'); } +"+" { return('+'); } +"*" { if (parbal && notype == 0) notype = 1; return('*'); } +"/" { yylval.intval = DIV; return(C_DIVOP); } +"%" { yylval.intval = MOD; return(C_DIVOP); } +"<" { yylval.intval = LT; return(C_RELOP); } +">" { yylval.intval = GT; return(C_RELOP); } +"^" { return('^'); } +"|" { return('|'); } +"?" { return('?'); } +^#pragma[ \t].* { pragma(); } +^#ident[ \t].* { control(CPP_IDENT); } +^#line[ \t].* { control(CPP_LINE); } +^#.* { control(CPP_HASH); } + +[ \t\v\f] { } +"\n" { ++lineno; STABS_LINE(lineno); } +. { /* ignore bad characters */ } + +%% + +int lineno; +char *ftitle = ""; + +int +yywrap(void) +{ + if (0) unput(0); /* quiet gcc */ + return(1); +} + +int +resw(TWORD t, int rv) +{ + if (inattr) { + yylval.strp = addname(yytext); + return C_NAME; + } + + switch (rv) { + case C_CLASS: + yylval.nodep = block(CLASS, NIL, NIL, t, 0, 0); + return rv; + + case C_QUALIFIER: + yylval.nodep = block(QUALIFIER, NIL, NIL, 0, 0, 0); + yylval.nodep->n_qual = t; + return rv; + + case C_TYPE: + yylval.nodep = mkty(t, 0, MKAP(t)); + notype=1; + return(rv); + + default: + cerror("resw"); + } + return 0; +} + +#ifndef SOFTFLOAT + +static long double +typround(long double dc, char *e, TWORD *tw) +{ + int im = 0; + + *tw = DOUBLE; + for (; *e; e++) { + switch (*e) { + case 'f': + case 'F': + *tw = FLOAT; + dc = (float)dc; + break; + case 'l': + case 'L': + *tw = LDOUBLE; + break; + case 'i': + case 'I': + im = 1; + break; + } + } + if (*tw == DOUBLE) + dc = (double)dc; +#ifndef NO_COMPLEX + if (im) + *tw += (FIMAG-FLOAT); +#endif + return dc; +} + +/* + * XXX floatcon() and fhexcon() should be in support libraries for + * the target floating point. + */ +static NODE * +f2(char *str) +{ + TWORD tw; + NODE *p; + long double dc; + char *eptr; + +#ifdef HAVE_STRTOLD + dc = strtold(str, &eptr); /* XXX - avoid strtod() */ +#else + dc = strtod(str, &eptr); /* XXX - avoid strtod() */ +#endif + dc = typround(dc, eptr, &tw); + p = block(FCON, NIL, NIL, tw, 0, MKAP(tw)); + p->n_dcon = dc; + return p; +} + +NODE * +floatcon(char *s) +{ + return f2(s); +} + +static int +h2n(int ch) +{ + if (ch >= '0' && ch <= '9') + return ch - '0'; + if (ch >= 'a' && ch <= 'f') + return ch - 'a' + 10; + return ch - 'A' + 10; + +} + +NODE * +fhexcon(char *c) +{ + TWORD tw; + char *ep; + long double d; + int i, ed; + NODE *p; + + d = 0.0; + ed = 0; + c+= 2; /* skip 0x */ +#define FSET(n) { d *= 2; if (i & n) d += 1.0; } + for (; *c != '.' && *c != 'p' && *c != 'P'; c++) { + i = h2n(*c); + FSET(8); FSET(4); FSET(2); FSET(1); + } + if (*c != '.' && *c != 'p' && *c != 'P') + cerror("fhexcon"); + if (*c == '.') { + c++; + for (; *c != 'p' && *c != 'P'; c++) { + i = h2n(*c); + FSET(8); FSET(4); FSET(2); FSET(1); + ed -= 4; + } + } + if (*c != 'P' && *c != 'p') + cerror("fhexcon2"); + c++; + ed += strtol(c, &ep, 10); + + /* avoid looping in vain. Idea from Fred J. Tydeman */ + if (ed > 32769) ed = 32769; + if (ed < -32769) ed = -32769; + + while (ed > 0) + d *= 2, ed--; + while (ed < 0) + d /= 2, ed++; + d = typround(d, ep, &tw); + p = block(FCON, NIL, NIL, tw, 0, MKAP(tw)); + p->n_dcon = d; + return p; +} +#endif + +unsigned int +esccon(char **sptr) +{ + char *wr = *sptr; + char *owr; + char c; + unsigned int val; + int wsz = 4, esccon_warn = 1; + + switch (*wr++) { + case 'a': val = '\a'; break; + case 'b': val = '\b'; break; + case 'f': val = '\f'; break; + case 'n': val = '\n'; break; + case 'r': val = '\r'; break; + case 't': val = '\t'; break; + case 'v': val = '\v'; break; + case '\"': val = '\"'; break; + case 'x': val = strtoul(wr, &wr, 16); break; + /* ISO/IEC 9099:1999 (E) 6.4.3 */ + case 'U'|(char)0x80: + esccon_warn = 0; + /* FALLTHROUGH */ + case 'U': + wsz = 8; + /* FALLTHROUGH */ + case 'u': + owr = wr; + while (wr < (owr + wsz)) + if (*wr == '\0') + break; + else + ++wr; + if (wr != (owr + wsz)) { + /* incomplete */ + val = strtoul(owr, &wr, 16); + } else { + c = owr[wsz]; + owr[wsz] = '\0'; /* prevent it from reading too much */ + val = strtoul(owr, &wr, 16); + owr[wsz] = c; + } + if (wr != (owr + wsz)) + werror("incomplete universal character name"); + if (wsz == 4) + val &= 0xFFFF; + if (esccon_warn && ((val >= 0xD800 && val <= 0xDFFF) || + (val < 0xA0 && val != 0x24 && val != 0x40 && val != 0x60))) + werror("invalid universal character name %04X", val); + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': + val = wr[-1] - '0'; + if (*wr >= '0' && *wr <= '7') { + val = (val << 3) + (*wr++ - '0'); + if (*wr >= '0' && *wr <= '7') + val = (val << 3) + (*wr++ - '0'); + } + break; + default: val = wr[-1]; + } + *sptr = wr; + return val; +} + +NODE * +cvtdig(int radix) +{ + NODE *p; + TWORD ntype; + unsigned long long v; + char *ch = yytext; + int n, numl, numu; + + if (radix == 16) + ch += 2; /* Skip 0x */ + + v = 0; + while ((*ch >= '0' && *ch <= '9') || (*ch >= 'a' && *ch <= 'f') || + (*ch >= 'A' && *ch <= 'F')) { + v *= radix; + n = *ch; + n = (n <= '9' ? n - '0' : (n > 'F' ? n - 'a' : n - 'A') + 10); + ch++; + v += n; + } + /* Parse trailing chars */ + ntype = INT; + numl = numu = 0; + for (n = 0; n < 3; n++) { + if (*ch == 0) + break; + if ((*ch == 'l' || *ch == 'L') && numl < 2) + ntype+=2, numl++; + else if ((*ch == 'u' || *ch == 'U') && numu < 1) + ntype = ENUNSIGN(ntype), numu++; + else + break; + ch++; + } + if (*ch) + uerror("constant has too many '%c'", *ch); + + if (ntype == INT) { + /* v contains a number. Get type correct */ + if (v > MAX_LONGLONG && radix != 10) + ntype = ULONGLONG; + else if (v > MAX_ULONG) + ntype = LONGLONG; + else if (v > MAX_LONG && radix != 10) + ntype = ULONG; + else if (v > MAX_UNSIGNED) + ntype = LONG; + else if (v > MAX_INT && radix != 10) + ntype = UNSIGNED; + } + ntype = ctype(ntype); + p = xbcon(v, NULL, ntype); + ASGLVAL(p->n_slval, v); + + return p; +} + +/* + * Convert a character constant to an integer. + */ +NODE * +charcon(void) +{ + int lastcon = 0; + int val, i = 0; + char *pp = yytext; + + if (*pp == 'L') + pp++; + pp++; + while (*pp != '\'') { + if (*pp++ == '\\') { + val = esccon(&pp); + } else + val = pp[-1]; + makecc(val, i); + i++; + } + + if (i == 0) + uerror("empty character constant"); + if (i > (SZINT/SZCHAR) || (i>1)) + werror("too many characters in character constant"); + return bcon(lastcon); +} + +NODE * +wcharcon(void) +{ + unsigned int lastcon = 0; + unsigned int val, i = 0; + char *pp = yytext; + + if (*pp == 'L') + pp++; + pp++; + while (*pp != '\'') { + if (*pp++ == '\\') { + val = esccon(&pp); + } else + val = pp[-1]; +#if WCHAR_SIZE == 2 + lastcon = (lastcon << 16) | (val & 0xFFFF); +#else + lastcon = val; +#endif + i++; + } + + if (i == 0) + uerror("empty wide character constant"); + if (i > 1) + werror("too many characters in wide character constant"); + return xbcon(lastcon, NULL, ctype(UNSIGNED)); +} + +void +control(int t) +{ + char *wr = yytext; + char *eptr; + int val; + + wr++; /* Skip initial '#' */ + switch (t) { + case CPP_IDENT: + return; /* Just skip these for now. */ + + case CPP_LINE: + wr += 4; + /* FALLTHROUGH */ + case CPP_HASH: + val = strtol(wr, &eptr, 10); + if (wr == eptr) /* Illegal string */ + goto bad; + wr = eptr; + lineno = val - 1; + while (*wr && *wr != '\"') + wr++; + if (*wr == 0) + return; + if (*wr++ != '\"') + goto bad; + eptr = wr; + while (*wr && *wr != '\"') + wr++; + if (*wr != '\"') + goto bad; + *wr = 0; + ftitle = addstring(eptr); +#ifdef STABS + if (gflag) + stabs_file(ftitle); +#endif + } + return; +bad: + werror("%s: illegal control", yytext); +} + +int pragma_allpacked; +int pragma_packed, pragma_aligned; +char *pragma_renamed; + +static int +pragmas_weak(char *str) +{ + struct symtab *sp; + char *s1, *s2; + + if ((s1 = pragtok(NULL)) == NULL) + return 1; + if ((s2 = pragtok(NULL)) == NULL) { + sp = lookup(addname(s1), SNORMAL); + sp->sap = attr_add(sp->sap, gcc_attr_parse(bdty(NAME, "weak"))); + } else if (*s2 == '=') { + if ((s2 = pragtok(NULL)) == NULL) + return 1; + sp = lookup(addname(s2), SNORMAL); + sp->sap = attr_add(sp->sap, gcc_attr_parse(bdty(CALL, + bdty(NAME, "aliasweak"), bdty(STRING, s1, 0)))); + } else + return 1; + return 0; +} + +char *pragstore; + +/* trivial tokenizer for pragmas */ +#define ps pragstore +char * +pragtok(char *sin) +{ + static char ss[2]; + char *rv; + + if (sin) + ps = sin; + + for (; isspace((int)*ps); ps++) + ; + if (*ps == 0) + return NULL; + for (rv = ps; isalpha((int)*ps) || isdigit((int)*ps) || *ps == '_'; ps++) + ; + ss[0] = *ps; + if (rv == ps) { + rv = ss, ps++; + } else { + *ps = 0; + rv = tmpstrdup(rv); + *ps = ss[0]; + } + return rv; +} + +/* return 1 on error */ +int +eat(int ch) +{ + char *s = pragtok(0); + return (s == 0 || *s != ch); +} + +static int +pragmas_alpack(char *t) +{ + char *s; + int ap; + + ap = (s = pragtok(0)) ? atoi(s) : 1; + if (strcmp(t, "packed") == 0) + pragma_packed = ap; + else + pragma_aligned = ap; + return 0; +} + + +/* + * Packing control. + * still missing push/pop. + */ +static int +pragmas_pack(char *t) +{ + char *s; + + if (eat('(')) + return 1; + s = pragtok(0); + if (*s == ')') + return pragma_allpacked = 0; + + if (*s < '0' || *s > '9') /* no number */ + return 1; + pragma_allpacked = atoi(s); + return eat(')'); +} + +static int +pragmas_renamed(char *t) +{ + char *f = pragtok(0); + + if (f == 0) + return 1; + pragma_renamed = newstring(f, strlen(f)); + return 0; +} + +static int +pragmas_stdc(char *t) +{ + return 0; /* Just ignore */ +} + +struct pragmas { + char *name; + int (*fun)(char *); +} pragmas[] = { + { "pack", pragmas_pack }, + { "packed", pragmas_alpack }, + { "aligned", pragmas_alpack }, + { "rename", pragmas_renamed }, +#ifdef GCC_COMPAT + { "GCC", pragmas_gcc }, +#endif + { "STDC", pragmas_stdc }, + { "weak", pragmas_weak }, + { "ident", NULL }, + { 0 }, +}; +/* + * got a full pragma line. Split it up here. + */ +static void +pragma() +{ + struct pragmas *p; + char *t, *pt; + + if ((t = pragtok(&yytext[7])) != NULL) { + pt = ps; + for (p = pragmas; p->name; p++) { + if (strcmp(t, p->name) == 0) { + if (p->fun && (*p->fun)(t)) + uerror("bad argument to #pragma"); + return; + } + } + ps = pt; + if (mypragma(t)) + return; + } + warner(Wunknown_pragmas, t, ps); +} + +void +cunput(char c) +{ + unput(c); +} diff --git a/compilers/pcc/pcc-1.0.0/cc/ccom/softfloat.c b/compilers/pcc/pcc-1.0.0/cc/ccom/softfloat.c new file mode 100644 index 00000000..12f17585 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/ccom/softfloat.c @@ -0,0 +1,359 @@ +/* $Id: softfloat.c,v 1.4 2009/07/29 12:32:34 ragge Exp $ */ + +/* + * Copyright (c) 2008 Anders Magnusson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef SOFTFLOAT + +#include "pass1.h" + + +/* + * Floating point emulation to be used when cross-compiling. + * Currently only supports F- and D-float, used in DEC machines. + * Should be trivial to add other emulations. + * + * XXX - assumes that: + * - long long is (at least) 64 bits + * - int is at least 32 bits. + * - short is 16 bits. + */ + +#ifdef FDFLOAT + +/* + * Useful macros to manipulate the float. + */ +#define DSIGN(w) (((w).fd1 >> 15) & 1) +#define DSIGNSET(w,s) ((w).fd1 = (s << 15) | ((w).fd1 & 077777)) +#define DEXP(w) (((w).fd1 >> 7) & 0377) +#define DEXPSET(w,e) ((w).fd1 = (((e) & 0377) << 7) | ((w).fd1 & 0100177)) +#define DMANTH(w) ((w).fd1 & 0177) +#define DMANTHSET(w,m) ((w).fd1 = ((m) & 0177) | ((w).fd1 & 0177600)) + +typedef unsigned int lword; +typedef unsigned long long dword; + +#define MAXMANT 0x100000000000000LL + +/* + * Returns a zero dfloat. + */ +static SF +nulldf(void) +{ + SF rv; + + rv.fd1 = rv.fd2 = rv.fd3 = rv.fd4 = 0; + return rv; +} + +/* + * Convert a (u)longlong to dfloat. + * XXX - fails on too large (> 55 bits) numbers. + */ +SF +soft_cast(CONSZ ll, TWORD t) +{ + int i; + SF rv; + + rv = nulldf(); + if (ll == 0) + return rv; /* fp is zero */ + if (ll < 0) + DSIGNSET(rv,1), ll = -ll; + for (i = 0; ll > 0; i++, ll <<= 1) + ; + DEXPSET(rv, 192-i); + DMANTHSET(rv, ll >> 56); + rv.fd2 = ll >> 40; + rv.fd3 = ll >> 24; + rv.fd4 = ll >> 8; + return rv; +} + +/* + * multiply two dfloat. Use chop, not round. + */ +SF +soft_mul(SF p1, SF p2) +{ + SF rv; + lword a1[2], a2[2], res[4]; + dword sum; + + res[0] = res[1] = res[2] = res[3] = 0; + + /* move mantissa into lwords */ + a1[0] = p1.fd4 | (p1.fd3 << 16); + a1[1] = p1.fd2 | DMANTH(p1) << 16 | 0x800000; + + a2[0] = p2.fd4 | (p2.fd3 << 16); + a2[1] = p2.fd2 | DMANTH(p2) << 16 | 0x800000; + +#define MULONE(x,y,r) sum += (dword)a1[x] * (dword)a2[y]; sum += res[r]; \ + res[r] = sum; sum >>= 32; + + sum = 0; + MULONE(0, 0, 0); + MULONE(1, 0, 1); + res[2] = sum; + sum = 0; + MULONE(0, 1, 1); + MULONE(1, 1, 2); + res[3] = sum; + + rv.fd1 = 0; + DSIGNSET(rv, DSIGN(p1) ^ DSIGN(p2)); + DEXPSET(rv, DEXP(p1) + DEXP(p2) - 128); + if (res[3] & 0x8000) { + res[3] = (res[3] << 8) | (res[2] >> 24); + res[2] = (res[2] << 8) | (res[1] >> 24); + } else { + DEXPSET(rv, DEXP(rv) - 1); + res[3] = (res[3] << 9) | (res[2] >> 23); + res[2] = (res[2] << 9) | (res[1] >> 23); + } + DMANTHSET(rv, res[3] >> 16); + rv.fd2 = res[3]; + rv.fd3 = res[2] >> 16; + rv.fd4 = res[2]; + return rv; +} + +SF +soft_div(SF t, SF n) +{ + SF rv; + dword T, N, K; + int c; + +#define SHL(x,b) ((dword)(x) << b) + T = SHL(1,55) | SHL(DMANTH(t), 48) | + SHL(t.fd2, 32) | SHL(t.fd3, 16) | t.fd4; + N = SHL(1,55) | SHL(DMANTH(n), 48) | + SHL(n.fd2, 32) | SHL(n.fd3, 16) | n.fd4; + + c = T > N; + for (K = 0; (K & 0x80000000000000ULL) == 0; ) { + if (T >= N) { + T -= N; + K |= 1; + } + T <<= 1; + K <<= 1; + } + rv.fd1 = 0; + DSIGNSET(rv, DSIGN(t) ^ DSIGN(n)); + DEXPSET(rv, DEXP(t) - DEXP(n) + 128 + c); + DMANTHSET(rv, K >> 48); + rv.fd2 = K >> 32; + rv.fd3 = K >> 16; + rv.fd4 = K; + return rv; +} + +/* + * Negate a float number. Easy. + */ +SF +soft_neg(SF sf) +{ + int sign = DSIGN(sf) == 0; + DSIGNSET(sf, sign); + return sf; +} + +/* + * Return true if fp number is zero. + */ +int +soft_isz(SF sf) +{ + return (DEXP(sf) == 0); +} + +int +soft_cmp_eq(SF x1, SF x2) +{ + cerror("soft_cmp_eq"); + return 0; +} + +int +soft_cmp_ne(SF x1, SF x2) +{ + cerror("soft_cmp_ne"); + return 0; +} + +int +soft_cmp_le(SF x1, SF x2) +{ + cerror("soft_cmp_le"); + return 0; +} + +int +soft_cmp_lt(SF x1, SF x2) +{ + cerror("soft_cmp_lt"); + return 0; +} + +int +soft_cmp_ge(SF x1, SF x2) +{ + cerror("soft_cmp_ge"); + return 0; +} + +int +soft_cmp_gt(SF x1, SF x2) +{ + cerror("soft_cmp_gt"); + return 0; +} + +/* + * Convert a fp number to a CONSZ. + */ +CONSZ +soft_val(SF sf) +{ + CONSZ mant; + int exp = DEXP(sf) - 128; + + mant = SHL(1,55) | SHL(DMANTH(sf), 48) | + SHL(sf.fd2, 32) | SHL(sf.fd3, 16) | sf.fd4; + + while (exp < 0) + mant >>= 1, exp++; + while (exp > 0) + mant <<= 1, exp--; + return mant; +} + +SF +soft_plus(SF x1, SF x2) +{ + cerror("soft_plus"); + return x1; +} + +SF +soft_minus(SF x1, SF x2) +{ + cerror("soft_minus"); + return x1; +} + +/* + * Convert a hex constant to floating point number. + */ +NODE * +fhexcon(char *s) +{ + cerror("fhexcon"); + return NULL; +} + +/* + * Convert a floating-point constant to D-float and store it in a NODE. + */ +NODE * +floatcon(char *s) +{ + NODE *p; + dword mant; + SF fl, flexp, exp5; + int exp, negexp, bexp; + + exp = 0; + mant = 0; +#define ADDTO(sum, val) sum = sum * 10 + val - '0' + for (; *s >= '0' && *s <= '9'; s++) { + if (mant= '0' && *s <= '9'; s++) { + if (mant= '0' && *s <= '9'; s++) + ADDTO(eexp, *s); + if (sign) + eexp = -eexp; + exp = exp + eexp; + } + + negexp = 1; + if (exp<0) { + negexp = -1; + exp = -exp; + } + + + flexp = soft_cast(1, INT); + exp5 = soft_cast(5, INT); + bexp = exp; + fl = soft_cast(mant, INT); + + for (; exp; exp >>= 1) { + if (exp&01) + flexp = soft_mul(flexp, exp5); + exp5 = soft_mul(exp5, exp5); + } + if (negexp<0) + fl = soft_div(fl, flexp); + else + fl = soft_mul(fl, flexp); + + DEXPSET(fl, DEXP(fl) + negexp*bexp); + p = block(FCON, NIL, NIL, DOUBLE, 0, MKSUE(DOUBLE)); /* XXX type */ + p->n_dcon = fl; + return p; +} +#else +#error missing softfloat definition +#endif +#endif diff --git a/compilers/pcc/pcc-1.0.0/cc/ccom/stabs.c b/compilers/pcc/pcc-1.0.0/cc/ccom/stabs.c new file mode 100644 index 00000000..39edb871 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/ccom/stabs.c @@ -0,0 +1,459 @@ +/* $Id: stabs.c,v 1.31 2010/08/11 14:08:44 ragge Exp $ */ + +/* + * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Simple implementation of the "stabs" debugging format. + * Not complete but at least makes it possible to set breakpoints, + * examine simple variables and do stack traces. + * Based on the stabs documentation that follows gdb. + */ + +#include "pass1.h" + +#ifdef STABS + +#include +#include +#include + +#define STABHASH 256 +#define INTNUM 1 /* internal number of type "int" */ +#undef BIT2BYTE /* from external.h */ +#define BIT2BYTE(x) ((x)/SZCHAR) + +#ifndef STABLBL +#error macdefs.h must define STABLBL +#endif + +/* defines taken from BSD */ +#define N_GSYM 0x20 /* global symbol */ +#define N_FUN 0x24 /* procedure name */ +#define N_LCSYM 0x28 /* bss segment variable */ +#define N_RSYM 0x40 /* register variable */ +#define N_SLINE 0x44 /* text segment line number */ +#define N_SO 0x64 /* main source file name */ +#define N_LSYM 0x80 /* stack variable */ +#define N_SOL 0x84 /* included source file name */ +#define N_PSYM 0xa0 /* parameter variable */ +#define N_LBRAC 0xc0 /* left bracket */ +#define N_RBRAC 0xe0 /* right bracket */ + +/* + * Local type mapping + * Types are defined as a typeword, a dimension pointer (in the case + * of arrays) and struct/union/enum declarations. + * Function prototypes are ignored. + */ +static struct stabtype { + struct stabtype *next; /* linked list */ + TWORD type; /* pcc type number */ + union dimfun *df; /* dimension of arrays */ + struct attr *ap; /* struct/union/enum declarations */ + int num; /* local type number */ +} *stabhash[STABHASH]; +static int ntypes; +static char *curfun; +static int stablbl = 10; +extern int inftn; + +void ptype(char *name, int num, int inhnum, long long min, long long max); +struct stabtype *addtype(TWORD, union dimfun *, struct attr *); +struct stabtype *findtype(TWORD t, union dimfun *df, struct attr *sue); +void printtype(struct symtab *s, char *str, int len); +void cprint(int p2, char *fmt, ...); + +#define MAXPSTR 100 + +extern int isinlining; + +/* + * Output type definitions for the stab debugging format. + * Note that "int" is always internal number 1. + */ +void +stabs_init() +{ + struct stabtype *st; + +#define ADDTYPE(y) addtype(y, NULL, MKAP(y)) + + ptype("int", ADDTYPE(INT)->num, INTNUM, MIN_INT, MAX_INT); + + st = ADDTYPE(CHAR); + ptype("char", st->num, st->num, 0, MAX_CHAR); + ptype("short", ADDTYPE(SHORT)->num, INTNUM, MIN_SHORT, MAX_SHORT); + ptype("long", ADDTYPE(LONG)->num, INTNUM, MIN_LONG, MAX_LONG); + ptype("long long", ADDTYPE(LONGLONG)->num, INTNUM, + MIN_LONGLONG, MAX_LONGLONG); + ptype("unsigned char", ADDTYPE(UCHAR)->num, INTNUM, 0, MAX_UCHAR); + ptype("unsigned short", ADDTYPE(USHORT)->num, INTNUM, 0, MAX_USHORT); + ptype("unsigned int", ADDTYPE(UNSIGNED)->num, INTNUM, 0, MAX_UNSIGNED); + ptype("unsigned long", ADDTYPE(ULONG)->num, INTNUM, 0, MAX_ULONG); + ptype("unsigned long long", ADDTYPE(ULONGLONG)->num, INTNUM, + 0, MAX_ULONGLONG); + + ptype("float", ADDTYPE(FLOAT)->num, INTNUM, 4, 0); + ptype("double", ADDTYPE(DOUBLE)->num, INTNUM, 8, 0); + ptype("long double", ADDTYPE(LDOUBLE)->num, INTNUM, 12, 0); + st = ADDTYPE(VOID); + cprint(0, "\t.stabs \"void:t%d=r%d\",%d,0,0,0\n", + st->num, st->num, N_LSYM); + +} + +/* + * Print a type in stabs format + */ +void +ptype(char *name, int num, int inhnum, long long min, long long max) +{ + cprint(0, "\t.stabs \"%s:t%d=r%d;%lld;%lld;\",%d,0,0,0\n", + name, num, inhnum, min, max, N_LSYM); +} + +/* + * Add a new local type to the hash table. + * The search key is the (type, df, sue) triple. + */ +struct stabtype * +addtype(TWORD t, union dimfun *df, struct attr *ap) +{ + struct stabtype *st; + + st = permalloc(sizeof(struct stabtype)); + st->type = t; + st->df = df; + st->ap = ap; + st->num = ++ntypes; + st->next = stabhash[t & (STABHASH-1)]; + stabhash[t & (STABHASH-1)] = st; + return st; +} + +/* + * Search for a given type and return a type pointer (or NULL). + */ +struct stabtype * +findtype(TWORD t, union dimfun *df, struct attr *ap) +{ + struct stabtype *st; + union dimfun *dw, *dx; + TWORD tw; + + st = stabhash[t & (STABHASH-1)]; + for (; st; st = st->next) { + if (t != st->type || ap != st->ap) + continue; + /* Ok, type and sue matches, check dimensions */ + if (st->df == NULL) + return st; /* no arrays, got match */ + dw = st->df; + dx = df; + tw = t; + for (; tw > BTMASK; tw = DECREF(tw)) { + if (ISARY(tw)) { + if (dw->ddim == dx->ddim) + dw++, dx++; + else + break; + } + } + if (tw <= BTMASK) + return st; + } + return NULL; +} + +/* + * Print current line number. + */ +void +stabs_line(int line) +{ + if (inftn == 0) + return; /* ignore */ +#ifdef STAB_LINE_ABSOLUTE + cprint(1, "\t.stabn %d,0,%d," STABLBL "\n" STABLBL ":\n", + N_SLINE, line, stablbl, stablbl); +#else + cprint(1, "\t.stabn %d,0,%d," STABLBL "-%s\n" STABLBL ":\n", + N_SLINE, line, stablbl, curfun, stablbl); +#endif + stablbl++; +} + +/* + * Start of block. + */ +void +stabs_lbrac(int blklvl) +{ +#ifdef STAB_LINE_ABSOLUTE + cprint(1, "\t.stabn %d,0,%d," STABLBL "\n" STABLBL ":\n", + N_LBRAC, blklvl, stablbl, stablbl); +#else + cprint(1, "\t.stabn %d,0,%d," STABLBL "-%s\n" STABLBL ":\n", + N_LBRAC, blklvl, stablbl, curfun, stablbl); +#endif + stablbl++; +} + +/* + * End of block. + */ +void +stabs_rbrac(int blklvl) +{ +#ifdef STAB_LINE_ABSOLUTE + cprint(1, "\t.stabn %d,0,%d," STABLBL "\n" STABLBL ":\n", + N_RBRAC, blklvl, stablbl, stablbl); +#else + cprint(1, "\t.stabn %d,0,%d," STABLBL "-%s\n" STABLBL ":\n", + N_RBRAC, blklvl, stablbl, curfun, stablbl); +#endif + stablbl++; +} + +static char *mainfile; + +/* + * Print current file and set mark. + */ +void +stabs_file(char *fname) +{ + if (mainfile == NULL) + mainfile = fname; /* first call */ + cprint(inftn, "\t.stabs \"%s\",%d,0,0," STABLBL "\n" STABLBL ":\n", + fname, fname == mainfile ? N_SO : N_SOL, stablbl, stablbl); + stablbl++; +} + +/* + * Print end mark + */ +void +stabs_efile(char *fname) +{ + cprint(inftn, "\t.stabs \"\",%d,0,0," STABLBL "\n" STABLBL ":\n", + fname == mainfile ? N_SO : N_SOL, stablbl, stablbl); + stablbl++; +} + +/* + * Print beginning of function. + */ +void +stabs_func(struct symtab *s) +{ + char str[MAXPSTR]; + + if ((curfun = s->soname) == NULL) + curfun = addname(exname(s->sname)); + printtype(s, str, sizeof(str)); + cprint(1, "\t.stabs \"%s:%c%s\",%d,0,%d,%s\n", + curfun, s->sclass == STATIC ? 'f' : 'F', str, + N_FUN, 0, curfun); +} + +/* + * Print a (complex) type. + * Will also create subtypes. + * Printed string is like "20=*21=*1". + */ +void +printtype(struct symtab *s, char *ostr, int len) +{ + struct stabtype *st; + union dimfun *df = s->sdf; + struct attr *ap = s->sap; + TWORD t = s->stype; + int op = 0; + + /* Print out not-yet-found types */ + if (ISFTN(t)) + t = DECREF(t); + st = findtype(t, df, ap); + while (st == NULL && t > BTMASK) { + st = addtype(t, df, ap); + op+=snprintf(ostr+op, len - op, "%d=", st->num); + if (ISFTN(t)) + ostr[op++] = 'f'; + else if (ISPTR(t)) + ostr[op++] = '*'; + else if (ISARY(t)) { + op+=snprintf(ostr+op, len - op, "ar%d;0;%d;", INTNUM, df->ddim-1); + } else + cerror("printtype: notype"); + if (ISARY(t)) + df++; + t = DECREF(t); + st = findtype(t, df, ap); + if (op > MAXPSTR-10) + cerror("printtype: too difficult expression"); + } + /* print out basic type. may have to be entered in case of sue */ + snprintf(ostr+op, len - op, "%d", st == NULL ? 1 : st->num); + /* snprintf here null-terminated the string */ +} + +void +stabs_newsym(struct symtab *s) +{ + extern int fun_inline; + char *sname; + char ostr[MAXPSTR]; + int suesize, sz; + + if (ISFTN(s->stype)) + return; /* functions are handled separate */ + + if (s->sclass == STNAME || s->sclass == UNAME || s->sclass == MOS || + s->sclass == ENAME || s->sclass == MOU || s->sclass == MOE || + s->sclass == TYPEDEF || (s->sclass & FIELD) || ISSOU(s->stype)) + return; /* XXX - fix structs */ + + if ((sname = s->soname) == NULL) + sname = exname(s->sname); + sz = tsize(s->stype, s->sdf, s->sap); + suesize = BIT2BYTE(sz); + if (suesize > 32767) + suesize = 32767; + else if (suesize < -32768) + suesize = -32768; + + printtype(s, ostr, sizeof(ostr)); + switch (s->sclass) { + case PARAM: + cprint(0, "\t.stabs \"%s:p%s\",%d,0,%d,%d\n", sname, ostr, + N_PSYM, suesize, BIT2BYTE(s->soffset)); + break; + + case AUTO: + cprint(0, "\t.stabs \"%s:%s\",%d,0,%d,%d\n", sname, ostr, + N_LSYM, suesize, BIT2BYTE(s->soffset)); + break; + + case STATIC: + if (blevel) + cprint(0, "\t.stabs \"%s:V%s\",%d,0,%d," LABFMT "\n", sname, ostr, + N_LCSYM, suesize, s->soffset); + else + cprint(0, "\t.stabs \"%s:S%s\",%d,0,%d,%s\n", sname, ostr, + N_LCSYM, suesize, sname); + break; + + case EXTERN: + case EXTDEF: + cprint(0, "\t.stabs \"%s:G%s\",%d,0,%d,0\n", sname, ostr, + N_GSYM, suesize); + break; + + case REGISTER: + cprint(0, "\t.stabs \"%s:r%s\",%d,0,%d,%d\n", sname, ostr, + N_RSYM, 1, s->soffset); + break; + case SNULL: + if (fun_inline) + break; + /* FALLTHROUGH */ + default: + cerror("fix stab_newsym; class %d", s->sclass); + } +} + +void +stabs_chgsym(struct symtab *s) +{ +} + +/* + * define a struct. + */ +void +stabs_struct(struct symtab *p, struct attr *ap) +{ +} + +struct stabsv { + SLIST_ENTRY(stabsv) next; + char *str; +} ; +static SLIST_HEAD(, stabsv) stpole = { NULL, &stpole.q_forw }; + +/* + * Global variable debug info is printed out directly. + * For functions and their declarations, both the labels and + * the debug info is put into ASM nodes and follows their statements + * into pass2. + * Due to the possible unsync between pass1 and 2 and where the + * stabs info for text is sent over the following syncing is used: + * curfun == 0 + * print out everything; only data will be. + * curfun != 0 && inftn == 0 + * save in linked list + * curfun != 0 && inftn != 0 + * print linked list first, empty it, then arg. + */ +void +cprint(int p2, char *fmt, ...) +{ +#define CPBSZ 200 + char buf[CPBSZ]; + struct stabsv *w; + va_list ap; + char *str; + + if (isinlining) + return; /* XXX do not save any inline functions currently */ + + va_start(ap, fmt); + if (p2) { + if (vsnprintf(buf, CPBSZ, fmt, ap) >= CPBSZ) + werror("stab symbol line too long, truncating"); + str = tmpstrdup(buf); + if (inftn == 0) { + w = tmpalloc(sizeof(struct stabsv)); + w->str = str; + SLIST_INSERT_LAST(&stpole, w, next); + } else { + if (stpole.q_last != &stpole.q_forw) { + SLIST_FOREACH(w, &stpole, next) { + send_passt(IP_ASM, w->str); + } + SLIST_INIT(&stpole); + } + send_passt(IP_ASM, str); + } + } else + vprintf(fmt, ap); + va_end(ap); +} + +#endif diff --git a/compilers/pcc/pcc-1.0.0/cc/ccom/symtabs.c b/compilers/pcc/pcc-1.0.0/cc/ccom/symtabs.c new file mode 100644 index 00000000..6229635a --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/ccom/symtabs.c @@ -0,0 +1,360 @@ +/* $Id: symtabs.c,v 1.19 2011/01/22 22:08:23 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "pass1.h" + +/* + * These definitions are used in the patricia tree that stores + * the strings. + */ +#define LEFT_IS_LEAF 0x80000000 +#define RIGHT_IS_LEAF 0x40000000 +#define IS_LEFT_LEAF(x) (((x) & LEFT_IS_LEAF) != 0) +#define IS_RIGHT_LEAF(x) (((x) & RIGHT_IS_LEAF) != 0) +#define BITNO(x) ((x) & ~(LEFT_IS_LEAF|RIGHT_IS_LEAF)) +#define CHECKBITS 8 + +struct tree { + int bitno; + struct tree *lr[2]; +}; + +static struct tree *firstname; +int nametabs, namestrlen; +static struct tree *firststr; +int strtabs, strstrlen; +static char *symtab_add(char *key, struct tree **, int *, int *); + +#define P_BIT(key, bit) (key[bit >> 3] >> (bit & 7)) & 1 +#define getree() permalloc(sizeof(struct tree)) + +char * +addname(char *key) +{ + return symtab_add(key, &firstname, &nametabs, &namestrlen); +} + +char * +addstring(char *key) +{ + return symtab_add(key, &firststr, &strtabs, &strstrlen); +} + +/* + * Add a name to the name stack (if its non-existing), + * return its address. + * This is a simple patricia implementation. + */ +char * +symtab_add(char *key, struct tree **first, int *tabs, int *stlen) +{ + struct tree *w, *new, *last; + int cix, bit, fbit, svbit, ix, bitno, len; + char *m, *k, *sm; + + /* Count full string length */ + for (k = key, len = 0; *k; k++, len++) + ; + + switch (*tabs) { + case 0: + *first = (struct tree *)newstring(key, len); + *stlen += (len + 1); + (*tabs)++; + return (char *)*first; + + case 1: + m = (char *)*first; + svbit = 0; /* XXX why? */ + break; + + default: + w = *first; + bitno = len * CHECKBITS; + for (;;) { + bit = BITNO(w->bitno); + fbit = bit > bitno ? 0 : P_BIT(key, bit); + svbit = fbit ? IS_RIGHT_LEAF(w->bitno) : + IS_LEFT_LEAF(w->bitno); + w = w->lr[fbit]; + if (svbit) { + m = (char *)w; + break; + } + } + } + + sm = m; + k = key; + + /* Check for correct string and return */ + for (cix = 0; *m && *k && *m == *k; m++, k++, cix += CHECKBITS) + ; + if (*m == 0 && *k == 0) + return sm; + + ix = *m ^ *k; + while ((ix & 1) == 0) + ix >>= 1, cix++; + + /* Create new node */ + new = getree(); + bit = P_BIT(key, cix); + new->bitno = cix | (bit ? RIGHT_IS_LEAF : LEFT_IS_LEAF); + new->lr[bit] = (struct tree *)newstring(key, len); + *stlen += (len + 1); + + if ((*tabs)++ == 1) { + new->lr[!bit] = *first; + new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF); + *first = new; + return (char *)new->lr[bit]; + } + + + w = *first; + last = NULL; + for (;;) { + fbit = w->bitno; + bitno = BITNO(w->bitno); + if (bitno == cix) + cerror("bitno == cix"); + if (bitno > cix) + break; + svbit = P_BIT(key, bitno); + last = w; + w = w->lr[svbit]; + if (fbit & (svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF)) + break; + } + + new->lr[!bit] = w; + if (last == NULL) { + *first = new; + } else { + last->lr[svbit] = new; + last->bitno &= ~(svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF); + } + if (bitno < cix) + new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF); + return (char *)new->lr[bit]; +} + +static struct tree *sympole[NSTYPES]; +static struct symtab *tmpsyms[NSTYPES]; +int numsyms[NSTYPES]; + +/* + * Inserts a symbol into the symbol tree. + * Returns a struct symtab. + */ +struct symtab * +lookup(char *key, int stype) +{ + struct symtab *sym; + struct tree *w, *new, *last; + int cix, bit, fbit, svbit, bitno; + int type, uselvl; + intptr_t ix, match, code = (intptr_t)key; + + type = stype & SMASK; + uselvl = (blevel > 0 && type != SSTRING); + + /* + * The local symbols are kept in a simple linked list. + * Check this list first. + */ + if (blevel > 0) + for (sym = tmpsyms[type]; sym; sym = sym->snext) + if (sym->sname == key) + return sym; + + switch (numsyms[type]) { + case 0: + if (stype & SNOCREAT) + return NULL; + if (uselvl) { + sym = getsymtab(key, stype|STEMP); + sym->snext = tmpsyms[type]; + tmpsyms[type] = sym; + return sym; + } + sympole[type] = (struct tree *)getsymtab(key, stype); + numsyms[type]++; + return (struct symtab *)sympole[type]; + + case 1: + w = (struct tree *)sympole[type]; + svbit = 0; /* XXX why? */ + break; + + default: + w = sympole[type]; + for (;;) { + bit = BITNO(w->bitno); + fbit = (code >> bit) & 1; + svbit = fbit ? IS_RIGHT_LEAF(w->bitno) : + IS_LEFT_LEAF(w->bitno); + w = w->lr[fbit]; + if (svbit) + break; + } + } + + sym = (struct symtab *)w; + match = (intptr_t)sym->sname; + + ix = code ^ match; + if (ix == 0) + return sym; + else if (stype & SNOCREAT) + return NULL; + +#ifdef PCC_DEBUG + if (ddebug) + printf(" adding %s as %s at level %d\n", + key, uselvl ? "temp" : "perm", blevel); +#endif + + /* + * Insert into the linked list, if feasible. + */ + if (uselvl) { + sym = getsymtab(key, stype|STEMP); + sym->snext = tmpsyms[type]; + tmpsyms[type] = sym; + return sym; + } + + /* + * Need a new node. If type is SNORMAL and inside a function + * the node must be allocated as permanent anyway. + * This could be optimized by adding a remove routine, but it + * may be more trouble than it is worth. + */ + if (stype == (STEMP|SNORMAL)) + stype = SNORMAL; + + for (cix = 0; (ix & 1) == 0; ix >>= 1, cix++) + ; + + new = stype & STEMP ? tmpalloc(sizeof(struct tree)) : + permalloc(sizeof(struct tree)); + bit = (code >> cix) & 1; + new->bitno = cix | (bit ? RIGHT_IS_LEAF : LEFT_IS_LEAF); + new->lr[bit] = (struct tree *)getsymtab(key, stype); + if (numsyms[type]++ == 1) { + new->lr[!bit] = sympole[type]; + new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF); + sympole[type] = new; + return (struct symtab *)new->lr[bit]; + } + + + w = sympole[type]; + last = NULL; + for (;;) { + fbit = w->bitno; + bitno = BITNO(w->bitno); + if (bitno == cix) + cerror("bitno == cix"); + if (bitno > cix) + break; + svbit = (code >> bitno) & 1; + last = w; + w = w->lr[svbit]; + if (fbit & (svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF)) + break; + } + + new->lr[!bit] = w; + if (last == NULL) { + sympole[type] = new; + } else { + last->lr[svbit] = new; + last->bitno &= ~(svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF); + } + if (bitno < cix) + new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF); + return (struct symtab *)new->lr[bit]; +} + +void +symclear(int level) +{ + struct symtab *s; + int i; + +#ifdef PCC_DEBUG + if (ddebug) + printf("symclear(%d)\n", level); +#endif + if (level < 1) { + for (i = 0; i < NSTYPES; i++) { + s = tmpsyms[i]; + tmpsyms[i] = 0; + if (i != SLBLNAME) + continue; + while (s != NULL) { + if (s->soffset < 0) + uerror("label '%s' undefined",s->sname); + s = s->snext; + } + } + } else { + for (i = 0; i < NSTYPES; i++) { + if (i == SLBLNAME) + continue; /* function scope */ + while (tmpsyms[i] != NULL && + tmpsyms[i]->slevel > level) { + tmpsyms[i] = tmpsyms[i]->snext; + } + } + } +} + +struct symtab * +hide(struct symtab *sym) +{ + struct symtab *new; + int typ = sym->sflags & SMASK; + + new = getsymtab(sym->sname, typ|STEMP); + new->snext = tmpsyms[typ]; + tmpsyms[typ] = new; + + warner(Wshadow, sym->sname, sym->slevel ? "local" : "global"); + +#ifdef PCC_DEBUG + if (ddebug) + printf("\t%s hidden at level %d (%p -> %p)\n", + sym->sname, blevel, sym, new); +#endif + return new; +} diff --git a/compilers/pcc/pcc-1.0.0/cc/ccom/trees.c b/compilers/pcc/pcc-1.0.0/cc/ccom/trees.c new file mode 100644 index 00000000..b029d00e --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/ccom/trees.c @@ -0,0 +1,2896 @@ +/* $Id: trees.c,v 1.272.2.1 2011/03/01 17:39:28 ragge Exp $ */ +/* + * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code and documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditionsand the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Some of the changes from 32V include: + * - Understand "void" as type. + * - Handle enums as ints everywhere. + * - Convert some C-specific ops into branches. + */ + +# include "pass1.h" +# include "pass2.h" + +# include +# include + +static void chkpun(NODE *p); +static int opact(NODE *p); +static int moditype(TWORD); +static NODE *strargs(NODE *); +static void rmcops(NODE *p); +void putjops(NODE *, void *); +static struct symtab *findmember(struct symtab *, char *); +int inftn; /* currently between epilog/prolog */ + +static char *tnames[] = { + "undef", + "farg", + "char", + "unsigned char", + "short", + "unsigned short", + "int", + "unsigned int", + "long", + "unsigned long", + "long long", + "unsigned long long", + "float", + "double", + "long double", + "strty", + "unionty", + "enumty", + "moety", + "void", + "signed", /* pass1 */ + "bool", /* pass1 */ + "fimag", /* pass1 */ + "dimag", /* pass1 */ + "limag", /* pass1 */ + "fcomplex", /* pass1 */ + "dcomplex", /* pass1 */ + "lcomplex", /* pass1 */ + "enumty", /* pass1 */ + "?", "?" +}; + +/* some special actions, used in finding the type of nodes */ +# define NCVT 01 +# define PUN 02 +# define TYPL 04 +# define TYPR 010 +# define TYMATCH 040 +# define LVAL 0100 +# define CVTO 0200 +# define CVTL 0400 +# define CVTR 01000 +# define PTMATCH 02000 +# define OTHER 04000 +# define NCVTR 010000 + +/* node conventions: + + NAME: rval>0 is stab index for external + rval<0 is -inlabel number + lval is offset in bits + ICON: lval has the value + rval has the STAB index, or - label number, + if a name whose address is in the constant + rval = NONAME means no name + REG: rval is reg. identification cookie + + */ + +int bdebug = 0; +extern int negrel[]; + +NODE * +buildtree(int o, NODE *l, NODE *r) +{ + NODE *p, *q; + int actions; + int opty; + struct symtab *sp = NULL; /* XXX gcc */ + NODE *lr, *ll; + +#ifdef PCC_DEBUG + if (bdebug) { + printf("buildtree(%s, %p, %p)\n", copst(o), l, r); + if (l) fwalk(l, eprint, 0); + if (r) fwalk(r, eprint, 0); + } +#endif + opty = coptype(o); + + /* check for constants */ + + if (o == ANDAND || o == OROR || o == NOT) { + if (l->n_op == FCON) { + p = bcon(!FLOAT_ISZERO(l->n_dcon)); + nfree(l); + l = p; + } + if (o != NOT && r->n_op == FCON) { + p = bcon(!FLOAT_ISZERO(r->n_dcon)); + nfree(r); + r = p; + } + } + + if( opty == UTYPE && l->n_op == ICON ){ + + switch( o ){ + + case NOT: + case UMINUS: + case COMPL: + if( conval( l, o, l ) ) return(l); + break; + } + } else if (o == NOT && l->n_op == FCON) { + l = clocal(block(SCONV, l, NIL, INT, 0, MKAP(INT))); + } else if( o == UMINUS && l->n_op == FCON ){ + l->n_dcon = FLOAT_NEG(l->n_dcon); + return(l); + + } else if( o==QUEST && l->n_op==ICON ) { + CONSZ c = l->n_lval; + nfree(l); + if (c) { + walkf(r->n_right, putjops, 0); + tfree(r->n_right); + l = r->n_left; + } else { + walkf(r->n_left, putjops, 0); + tfree(r->n_left); + l = r->n_right; + } + nfree(r); + return(l); + } else if( opty == BITYPE && l->n_op == ICON && r->n_op == ICON ){ + + switch( o ){ + + case PLUS: + case MINUS: + case MUL: + case DIV: + case MOD: + /* + * Do type propagation for simple types here. + * The constant value is correct anyway. + * Maybe this op shortcut should be removed? + */ + if (l->n_sp == NULL && r->n_sp == NULL && + l->n_type < BTMASK && r->n_type < BTMASK) { + if (l->n_type > r->n_type) + r->n_type = l->n_type; + else + l->n_type = r->n_type; + } + /* FALLTHROUGH */ + case ULT: + case UGT: + case ULE: + case UGE: + case LT: + case GT: + case LE: + case GE: + case EQ: + case NE: + case ANDAND: + case OROR: + case AND: + case OR: + case ER: + case LS: + case RS: + if (!ISPTR(l->n_type) && !ISPTR(r->n_type)) { + if( conval( l, o, r ) ) { + nfree(r); + return(l); + } + } + break; + } + } else if (opty == BITYPE && (l->n_op == FCON || l->n_op == ICON) && + (r->n_op == FCON || r->n_op == ICON) && (o == PLUS || o == MINUS || + o == MUL || o == DIV || (o >= EQ && o <= GT) )) { + TWORD t; +#ifndef CC_DIV_0 + if (o == DIV && + ((r->n_op == ICON && r->n_lval == 0) || + (r->n_op == FCON && r->n_dcon == 0.0))) + goto runtime; /* HW dependent */ +#endif + if (l->n_op == ICON) + l->n_dcon = FLOAT_CAST(l->n_lval, l->n_type); + if (r->n_op == ICON) + r->n_dcon = FLOAT_CAST(r->n_lval, r->n_type); + switch(o){ + case PLUS: + case MINUS: + case MUL: + case DIV: + switch (o) { + case PLUS: + l->n_dcon = FLOAT_PLUS(l->n_dcon, r->n_dcon); + break; + case MINUS: + l->n_dcon = FLOAT_MINUS(l->n_dcon, r->n_dcon); + break; + case MUL: + l->n_dcon = FLOAT_MUL(l->n_dcon, r->n_dcon); + break; + case DIV: + l->n_dcon = FLOAT_DIV(l->n_dcon, r->n_dcon); + break; + } + t = (l->n_type > r->n_type ? l->n_type : r->n_type); + l->n_op = FCON; + l->n_type = t; + l->n_ap = MKAP(t); + nfree(r); + return(l); + case EQ: + case NE: + case LE: + case LT: + case GE: + case GT: + switch (o) { + case EQ: + l->n_lval = FLOAT_EQ(l->n_dcon, r->n_dcon); + break; + case NE: + l->n_lval = FLOAT_NE(l->n_dcon, r->n_dcon); + break; + case LE: + l->n_lval = FLOAT_LE(l->n_dcon, r->n_dcon); + break; + case LT: + l->n_lval = FLOAT_LT(l->n_dcon, r->n_dcon); + break; + case GE: + l->n_lval = FLOAT_GE(l->n_dcon, r->n_dcon); + break; + case GT: + l->n_lval = FLOAT_GT(l->n_dcon, r->n_dcon); + break; + } + nfree(r); + r = bcon(l->n_lval); + nfree(l); + return r; + } + } +#ifndef CC_DIV_0 +runtime: +#endif + /* its real; we must make a new node */ + + p = block(o, l, r, INT, 0, MKAP(INT)); + + actions = opact(p); + + if (actions & LVAL) { /* check left descendent */ + if (notlval(p->n_left)) { + uerror("lvalue required"); + nfree(p); + return l; +#ifdef notyet + } else { + if ((l->n_type > BTMASK && ISCON(l->n_qual)) || + (l->n_type <= BTMASK && ISCON(l->n_qual << TSHIFT))) + if (blevel > 0) + uerror("lvalue is declared const"); +#endif + } + } + + if( actions & NCVTR ){ + p->n_left = pconvert( p->n_left ); + } + else if( !(actions & NCVT ) ){ + switch( opty ){ + + case BITYPE: + p->n_right = pconvert( p->n_right ); + case UTYPE: + p->n_left = pconvert( p->n_left ); + + } + } + + if ((actions&PUN) && (o!=CAST)) + chkpun(p); + + if( actions & (TYPL|TYPR) ){ + + q = (actions&TYPL) ? p->n_left : p->n_right; + + p->n_type = q->n_type; + p->n_qual = q->n_qual; + p->n_df = q->n_df; + p->n_ap = q->n_ap; + } + + if( actions & CVTL ) p = convert( p, CVTL ); + if( actions & CVTR ) p = convert( p, CVTR ); + if( actions & TYMATCH ) p = tymatch(p); + if( actions & PTMATCH ) p = ptmatch(p); + + if( actions & OTHER ){ + struct symtab *sp1; + + l = p->n_left; + r = p->n_right; + + switch(o){ + + case NAME: + cerror("buildtree NAME"); + + case STREF: + /* p->x turned into *(p+offset) */ + /* rhs must be a name; check correctness */ + + /* Find member symbol struct */ + if (l->n_type != PTR+STRTY && l->n_type != PTR+UNIONTY){ + uerror("struct or union required"); + break; + } + + if ((sp1 = strmemb(l->n_ap)) == NULL) { + uerror("undefined struct or union"); + break; + } + + if ((sp = findmember(sp1, r->n_name)) == NULL) { + uerror("member '%s' not declared", r->n_name); + break; + } + + r->n_sp = sp; + p = stref(p); + break; + + case UMUL: + if (l->n_op == ADDROF) { + nfree(p); + p = l->n_left; + nfree(l); + } + if( !ISPTR(l->n_type))uerror("illegal indirection"); + p->n_type = DECREF(l->n_type); + p->n_qual = DECREF(l->n_qual); + p->n_df = l->n_df; + p->n_ap = l->n_ap; + break; + + case ADDROF: + switch( l->n_op ){ + + case UMUL: + nfree(p); + p = l->n_left; + nfree(l); + case TEMP: + case NAME: + p->n_type = INCREF(l->n_type); + p->n_qual = INCQAL(l->n_qual); + p->n_df = l->n_df; + p->n_ap = l->n_ap; + break; + + case COMOP: + nfree(p); + lr = buildtree(ADDROF, l->n_right, NIL); + p = buildtree( COMOP, l->n_left, lr ); + nfree(l); + break; + + case QUEST: + lr = buildtree( ADDROF, l->n_right->n_right, NIL ); + ll = buildtree( ADDROF, l->n_right->n_left, NIL ); + nfree(p); nfree(l->n_right); + p = buildtree( QUEST, l->n_left, buildtree( COLON, ll, lr ) ); + nfree(l); + break; + + default: + uerror("unacceptable operand of &: %d", l->n_op ); + break; + } + break; + + case LS: + case RS: /* must make type size at least int... */ + if (p->n_type == CHAR || p->n_type == SHORT) { + p->n_left = makety(l, INT, 0, 0, MKAP(INT)); + } else if (p->n_type == UCHAR || p->n_type == USHORT) { + p->n_left = makety(l, UNSIGNED, 0, 0, + MKAP(UNSIGNED)); + } + l = p->n_left; + p->n_type = l->n_type; + p->n_qual = l->n_qual; + p->n_df = l->n_df; + p->n_ap = l->n_ap; + + /* FALLTHROUGH */ + case LSEQ: + case RSEQ: /* ...but not for assigned types */ + if(tsize(r->n_type, r->n_df, r->n_ap) > SZINT) + p->n_right = makety(r, INT, 0, 0, MKAP(INT)); + break; + + case RETURN: + case ASSIGN: + case CAST: + /* structure assignment */ + /* take the addresses of the two sides; then make an + * operator using STASG and + * the addresses of left and right */ + + if (strmemb(l->n_ap) != strmemb(r->n_ap)) + uerror("assignment of different structures"); + + r = buildtree(ADDROF, r, NIL); + + l = block(STASG, l, r, r->n_type, r->n_df, r->n_ap); + l = clocal(l); + + if( o == RETURN ){ + nfree(p); + p = l; + break; + } + + p->n_op = UMUL; + p->n_left = l; + p->n_right = NIL; + break; + + case QUEST: /* fixup types of : */ + if (r->n_left->n_type != p->n_type) + r->n_left = makety(r->n_left, p->n_type, + p->n_qual, p->n_df, p->n_ap); + if (r->n_right->n_type != p->n_type) + r->n_right = makety(r->n_right, p->n_type, + p->n_qual, p->n_df, p->n_ap); + break; + + case COLON: + /* structure colon */ + + if (strmemb(l->n_ap) != strmemb(r->n_ap)) + uerror( "type clash in conditional" ); + break; + + case CALL: + p->n_right = r = strargs(p->n_right); + p = funcode(p); + /* FALLTHROUGH */ + case UCALL: + if (!ISPTR(l->n_type)) + uerror("illegal function"); + p->n_type = DECREF(l->n_type); + if (!ISFTN(p->n_type)) + uerror("illegal function"); + p->n_type = DECREF(p->n_type); + p->n_df = l->n_df+1; /* add one for prototypes */ + p->n_ap = l->n_ap; + if (p->n_type == STRTY || p->n_type == UNIONTY) { + /* function returning structure */ + /* make function really return ptr to str., with * */ + + p->n_op += STCALL-CALL; + p->n_type = INCREF(p->n_type); + p = clocal(p); /* before recursing */ + p = buildtree(UMUL, p, NIL); + + } + break; + + default: + cerror( "other code %d", o ); + } + + } + + /* + * Allow (void)0 casts. + * XXX - anything on the right side must be possible to cast. + * XXX - remove void types further on. + */ + if (p->n_op == CAST && p->n_type == VOID && + p->n_right->n_op == ICON) + p->n_right->n_type = VOID; + + if (actions & CVTO) + p = oconvert(p); + p = clocal(p); + +#ifdef PCC_DEBUG + if (bdebug) { + printf("End of buildtree:\n"); + fwalk(p, eprint, 0); + } +#endif + + return(p); + + } + +/* Find a member in a struct or union. May be an unnamed member */ +static struct symtab * +findmember(struct symtab *sp, char *s) +{ + struct symtab *sp2, *sp3; + + for (; sp != NULL; sp = sp->snext) { + if (sp->sname[0] == '*') { + /* unnamed member, recurse down */ + if ((sp2 = findmember(strmemb(sp->sap), s))) { + sp3 = tmpalloc(sizeof (struct symtab)); + *sp3 = *sp2; + sp3->soffset += sp->soffset; + return sp3; + } + } else if (sp->sname == s) + return sp; + } + return NULL; +} + + +/* + * Check if there will be a lost label destination inside of a ?: + * It cannot be reached so just print it out. + */ +void +putjops(NODE *p, void *arg) +{ + if (p->n_op == COMOP && p->n_left->n_op == GOTO) + plabel(p->n_left->n_left->n_lval+1); +} + +/* + * Build a name node based on a symtab entry. + * broken out from buildtree(). + */ +NODE * +nametree(struct symtab *sp) +{ + NODE *p; + + p = block(NAME, NIL, NIL, sp->stype, sp->sdf, sp->sap); + p->n_qual = sp->squal; + p->n_sp = sp; + +#ifndef NO_C_BUILTINS + if (sp->sname[0] == '_' && strncmp(sp->sname, "__builtin_", 10) == 0) + return p; /* do not touch builtins here */ + +#endif + + if (sp->sflags & STNODE) { + /* Generated for optimizer */ + p->n_op = TEMP; + p->n_rval = sp->soffset; + } + +#ifdef GCC_COMPAT + /* Get a label name */ + if (sp->sflags == SLBLNAME) { + p->n_type = VOID; + p->n_ap = MKAP(VOID); + } +#endif + if (sp->stype == UNDEF) { + uerror("%s undefined", sp->sname); + /* make p look reasonable */ + p->n_type = INT; + p->n_ap = MKAP(INT); + p->n_df = NULL; + defid(p, SNULL); + } + if (sp->sclass == MOE) { + p->n_op = ICON; + p->n_lval = sp->soffset; + p->n_df = NULL; + p->n_sp = NULL; + } + return clocal(p); +} + +/* + * Cast a node to another type by inserting a cast. + * Just a nicer interface to buildtree. + * Returns the new tree. + */ +NODE * +cast(NODE *p, TWORD t, TWORD u) +{ + NODE *q; + + q = block(NAME, NIL, NIL, t, 0, MKAP(BTYPE(t))); + q->n_qual = u; + q = buildtree(CAST, q, p); + p = q->n_right; + nfree(q->n_left); + nfree(q); + return p; +} + +/* + * Cast and complain if necessary by not inserining a cast. + */ +NODE * +ccast(NODE *p, TWORD t, TWORD u, union dimfun *df, struct attr *ap) +{ + NODE *q; + + /* let buildtree do typechecking (and casting) */ + q = block(NAME, NIL, NIL, t, df, ap); + p = buildtree(ASSIGN, q, p); + nfree(p->n_left); + q = optim(p->n_right); + nfree(p); + return q; +} + +/* + * Do a conditional branch. + */ +void +cbranch(NODE *p, NODE *q) +{ + p = buildtree(CBRANCH, p, q); + if (p->n_left->n_op == ICON) { + if (p->n_left->n_lval != 0) { + branch(q->n_lval); /* branch always */ + reached = 0; + } + tfree(p); + tfree(q); + return; + } + ecomp(p); +} + +NODE * +strargs( p ) register NODE *p; { /* rewrite structure flavored arguments */ + + if( p->n_op == CM ){ + p->n_left = strargs( p->n_left ); + p->n_right = strargs( p->n_right ); + return( p ); + } + + if( p->n_type == STRTY || p->n_type == UNIONTY ){ + p = block(STARG, p, NIL, p->n_type, p->n_df, p->n_ap); + p->n_left = buildtree( ADDROF, p->n_left, NIL ); + p = clocal(p); + } + return( p ); +} + +/* + * apply the op o to the lval part of p; if binary, rhs is val + */ +int +conval(NODE *p, int o, NODE *q) +{ + TWORD tl = p->n_type, tr = q->n_type, td; + int i, u; + CONSZ val; + U_CONSZ v1, v2; + + val = q->n_lval; + + /* make both sides same type */ + if (tl < BTMASK && tr < BTMASK) { + td = tl > tr ? tl : tr; + if (td < INT) + td = INT; + u = ISUNSIGNED(td); + if (tl != td) + p = makety(p, td, 0, 0, MKAP(td)); + if (tr != td) + q = makety(q, td, 0, 0, MKAP(td)); + } else + u = ISUNSIGNED(tl) || ISUNSIGNED(tr); + if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE); + + if (p->n_sp != NULL && q->n_sp != NULL) + return(0); + if (q->n_sp != NULL && o != PLUS) + return(0); + if (p->n_sp != NULL && o != PLUS && o != MINUS) + return(0); + + v1 = p->n_lval; + v2 = q->n_lval; + switch( o ){ + + case PLUS: + p->n_lval += val; + if (p->n_sp == NULL) { + p->n_right = q->n_right; + p->n_type = q->n_type; + } + break; + case MINUS: + p->n_lval -= val; + break; + case MUL: + p->n_lval *= val; + break; + case DIV: + if (val == 0) + uerror("division by 0"); + else { + if (u) { + v1 /= v2; + p->n_lval = v1; + } else + p->n_lval /= val; + } + break; + case MOD: + if (val == 0) + uerror("division by 0"); + else { + if (u) { + v1 %= v2; + p->n_lval = v1; + } else + p->n_lval %= val; + } + break; + case AND: + p->n_lval &= val; + break; + case OR: + p->n_lval |= val; + break; + case ER: + p->n_lval ^= val; + break; + case LS: + i = (int)val; + p->n_lval = p->n_lval << i; + break; + case RS: + i = (int)val; + if (u) { + v1 = v1 >> i; + p->n_lval = v1; + } else + p->n_lval = p->n_lval >> i; + break; + + case UMINUS: + p->n_lval = - p->n_lval; + break; + case COMPL: + p->n_lval = ~p->n_lval; + break; + case NOT: + p->n_lval = !p->n_lval; + break; + case LT: + p->n_lval = p->n_lval < val; + break; + case LE: + p->n_lval = p->n_lval <= val; + break; + case GT: + p->n_lval = p->n_lval > val; + break; + case GE: + p->n_lval = p->n_lval >= val; + break; + case ULT: + p->n_lval = v1 < v2; + break; + case ULE: + p->n_lval = v1 <= v2; + break; + case UGT: + p->n_lval = v1 > v2; + break; + case UGE: + p->n_lval = v1 >= v2; + break; + case EQ: + p->n_lval = p->n_lval == val; + break; + case NE: + p->n_lval = p->n_lval != val; + break; + case ANDAND: + p->n_lval = p->n_lval && val; + break; + case OROR: + p->n_lval = p->n_lval || val; + break; + default: + return(0); + } + /* Do the best in making everything type correct after calc */ + if (p->n_sp == NULL && q->n_sp == NULL) + p->n_lval = valcast(p->n_lval, p->n_type); + return(1); + } + +/* + * Ensure that v matches the type t; sign- or zero-extended + * as suitable to CONSZ. + * Only to be used for integer types. + */ +CONSZ +valcast(CONSZ v, TWORD t) +{ + CONSZ r; + + if (t < CHAR || t > ULONGLONG) + return v; /* cannot cast */ + + if (t >= LONGLONG) + return v; /* already largest */ + +#define M(x) ((((1ULL << ((x)-1)) - 1) << 1) + 1) +#define NOTM(x) (~M(x)) +#define SBIT(x) (1ULL << ((x)-1)) + + r = v & M(btattr[t].atypsz); + if (!ISUNSIGNED(t) && (SBIT(btattr[t].atypsz) & r)) + r = r | NOTM(btattr[t].atypsz); + return r; +} + +/* + * Checks p for the existance of a pun. This is called when the op of p + * is ASSIGN, RETURN, CAST, COLON, or relational. + * One case is when enumerations are used: this applies only to lint. + * In the other case, one operand is a pointer, the other integer type + * we check that this integer is in fact a constant zero... + * in the case of ASSIGN, any assignment of pointer to integer is illegal + * this falls out, because the LHS is never 0. + * XXX - check for COMOPs in assignment RHS? + */ +void +chkpun(NODE *p) +{ + union dimfun *d1, *d2; + NODE *q; + int t1, t2; + + t1 = p->n_left->n_type; + t2 = p->n_right->n_type; + + switch (p->n_op) { + case RETURN: + /* return of void allowed but nothing else */ + if (t1 == VOID && t2 == VOID) + return; + if (t1 == VOID) { + werror("returning value from void function"); + return; + } + if (t2 == VOID) { + uerror("using void value"); + return; + } + case COLON: + if (t1 == VOID && t2 == VOID) + return; + break; + default: + if ((t1 == VOID && t2 != VOID) || (t1 != VOID && t2 == VOID)) { + uerror("value of void expression used"); + return; + } + break; + } + + /* allow void pointer assignments in any direction */ + if (BTYPE(t1) == VOID && (t2 & TMASK)) + return; + if (BTYPE(t2) == VOID && (t1 & TMASK)) + return; + + /* boolean have special syntax */ + if (t1 == BOOL) { + if (!ISARY(t2)) /* Anything scalar */ + return; + } + + if (ISPTR(t1) || ISARY(t1)) + q = p->n_right; + else + q = p->n_left; + + if (!ISPTR(q->n_type) && !ISARY(q->n_type)) { + if (q->n_op != ICON || q->n_lval != 0) + werror("illegal combination of pointer and integer"); + } else { + if (t1 == t2) { + if (ISSOU(BTYPE(t1)) && + !suemeq(p->n_left->n_ap, p->n_right->n_ap)) + werror("illegal structure pointer combination"); + return; + } + d1 = p->n_left->n_df; + d2 = p->n_right->n_df; + for (;;) { + if (ISARY(t1) || ISPTR(t1)) { + if (!ISARY(t2) && !ISPTR(t2)) + break; + if (ISARY(t1) && ISARY(t2) && d1->ddim != d2->ddim) { + werror("illegal array size combination"); + return; + } + if (ISARY(t1)) + ++d1; + if (ISARY(t2)) + ++d2; + } else if (ISFTN(t1)) { + if (chkftn(d1->dfun, d2->dfun)) { + werror("illegal function " + "pointer combination"); + return; + } + ++d1; + ++d2; + } else + break; + t1 = DECREF(t1); + t2 = DECREF(t2); + } + if (DEUNSIGN(t1) != DEUNSIGN(t2)) + warner(Wpointer_sign, NULL); + } +} + +NODE * +stref(NODE *p) +{ + NODE *r; + struct attr *ap; + union dimfun *d; + TWORD t, q; + int dsc; + OFFSZ off; + struct symtab *s; + + /* make p->x */ + /* this is also used to reference automatic variables */ + + s = p->n_right->n_sp; + nfree(p->n_right); + r = p->n_left; + nfree(p); + p = pconvert(r); + + /* make p look like ptr to x */ + + if (!ISPTR(p->n_type)) + p->n_type = PTR+UNIONTY; + + t = INCREF(s->stype); + q = INCQAL(s->squal); + d = s->sdf; + ap = s->sap; + + p = makety(p, t, q, d, ap); + + /* compute the offset to be added */ + + off = s->soffset; + dsc = s->sclass; + +#ifndef CAN_UNALIGN + /* + * If its a packed struct, and the target cannot do unaligned + * accesses, then split it up in two bitfield operations. + * LHS and RHS accesses are different, so must delay + * it until we know. Do the bitfield construct here though. + */ + if ((dsc & FIELD) == 0 && (off % talign(s->stype, s->sap))) { +#if 0 + int sz = tsize(s->stype, s->sdf, s->sap); + int al = talign(s->stype, s->sap); + int sz1 = al - (off % al); +#endif + } +#endif + +#if 0 + if (dsc & FIELD) { /* make fields look like ints */ + off = (off/ALINT)*ALINT; + ap = MKAP(INT); + } +#endif + if (off != 0) { + p = block(PLUS, p, offcon(off, t, d, ap), t, d, ap); + p->n_qual = q; + p = optim(p); + } + + p = buildtree(UMUL, p, NIL); + + /* if field, build field info */ + + if (dsc & FIELD) { + p = block(FLD, p, NIL, s->stype, 0, s->sap); + p->n_qual = q; + p->n_rval = PKFIELD(dsc&FLDSIZ, s->soffset%talign(s->stype, ap)); + } + + p = clocal(p); + return p; +} + +int +notlval(p) register NODE *p; { + + /* return 0 if p an lvalue, 1 otherwise */ + + again: + + switch( p->n_op ){ + + case FLD: + p = p->n_left; + goto again; + + case NAME: + case OREG: + case UMUL: + if( ISARY(p->n_type) || ISFTN(p->n_type) ) return(1); + case TEMP: + case REG: + return(0); + + default: + return(1); + + } + + } +/* make a constant node with value i */ +NODE * +bcon(int i) +{ + return xbcon(i, NULL, INT); +} + +NODE * +xbcon(CONSZ val, struct symtab *sp, TWORD type) +{ + NODE *p; + + p = block(ICON, NIL, NIL, type, 0, MKAP(type)); + p->n_lval = val; + p->n_sp = sp; + return clocal(p); +} + +NODE * +bpsize(NODE *p) +{ + int isdyn(struct symtab *sp); + struct attr *ap; + struct symtab s; + NODE *q, *r; + TWORD t; + + s.stype = DECREF(p->n_type); + s.sdf = p->n_df; + if (isdyn(&s)) { + q = bcon(1); + for (t = s.stype; t > BTMASK; t = DECREF(t)) { + if (ISPTR(t)) + return buildtree(MUL, q, bcon(SZPOINT(t))); + if (ISARY(t)) { + if (s.sdf->ddim < 0) + r = tempnode(-s.sdf->ddim, + INT, 0, MKAP(INT)); + else + r = bcon(s.sdf->ddim/SZCHAR); + q = buildtree(MUL, q, r); + s.sdf++; + } + } + ap = attr_find(p->n_ap, ATTR_BASETYP); + p = buildtree(MUL, q, bcon(ap->atypsz/SZCHAR)); + } else + p = (offcon(psize(p), p->n_type, p->n_df, p->n_ap)); + return p; +} + +/* + * p is a node of type pointer; psize returns the + * size of the thing pointed to + */ +OFFSZ +psize(NODE *p) +{ + + if (!ISPTR(p->n_type)) { + uerror("pointer required"); + return(SZINT); + } + /* note: no pointers to fields */ + return(tsize(DECREF(p->n_type), p->n_df, p->n_ap)); +} + +/* + * convert an operand of p + * f is either CVTL or CVTR + * operand has type int, and is converted by the size of the other side + * convert is called when an integer is to be added to a pointer, for + * example in arrays or structures. + */ +NODE * +convert(NODE *p, int f) +{ + union dimfun *df; + TWORD ty, ty2; + NODE *q, *r, *s, *rv; + + if (f == CVTL) { + q = p->n_left; + s = p->n_right; + } else { + q = p->n_right; + s = p->n_left; + } + ty2 = ty = DECREF(s->n_type); + while (ISARY(ty)) + ty = DECREF(ty); + + r = offcon(tsize(ty, s->n_df, s->n_ap), s->n_type, s->n_df, s->n_ap); + ty = ty2; + rv = bcon(1); + df = s->n_df; + while (ISARY(ty)) { + rv = buildtree(MUL, rv, df->ddim >= 0 ? bcon(df->ddim) : + tempnode(-df->ddim, INT, 0, MKAP(INT))); + df++; + ty = DECREF(ty); + } + rv = clocal(block(PMCONV, rv, r, INT, 0, MKAP(INT))); + rv = optim(rv); + + r = block(PMCONV, q, rv, INT, 0, MKAP(INT)); + r = clocal(r); + /* + * Indexing is only allowed with integer arguments, so insert + * SCONV here if arg is not an integer. + * XXX - complain? + */ + if (r->n_type != INTPTR) + r = clocal(block(SCONV, r, NIL, INTPTR, 0, MKAP(INTPTR))); + if (f == CVTL) + p->n_left = r; + else + p->n_right = r; + return(p); +} + +NODE * +pconvert( p ) register NODE *p; { + + /* if p should be changed into a pointer, do so */ + + if( ISARY( p->n_type) ){ + p->n_type = DECREF( p->n_type ); + ++p->n_df; + return( buildtree( ADDROF, p, NIL ) ); + } + if( ISFTN( p->n_type) ) + return( buildtree( ADDROF, p, NIL ) ); + + return( p ); + } + +NODE * +oconvert(p) register NODE *p; { + /* convert the result itself: used for pointer and unsigned */ + + switch(p->n_op) { + + case LE: + case LT: + case GE: + case GT: + if(ISUNSIGNED(p->n_left->n_type) || + ISUNSIGNED(p->n_right->n_type) || + ISPTR(p->n_left->n_type) || + ISPTR(p->n_right->n_type)) + p->n_op += (ULE-LE); + /* FALLTHROUGH */ + case EQ: + case NE: + return( p ); + + case MINUS: + p->n_type = INTPTR; + p->n_ap = MKAP(INTPTR); + return( clocal( block( PVCONV, + p, bpsize(p->n_left), INT, 0, MKAP(INT)))); + } + + cerror( "illegal oconvert: %d", p->n_op ); + + return(p); + } + +/* + * makes the operands of p agree; they are + * either pointers or integers, by this time + * with MINUS, the sizes must be the same + * with COLON, the types must be the same + */ +NODE * +ptmatch(NODE *p) +{ + struct attr *ap, *ap2; + union dimfun *d, *d2; + TWORD t1, t2, t, q1, q2, q; + int o; + + o = p->n_op; + t = t1 = p->n_left->n_type; + q = q1 = p->n_left->n_qual; + t2 = p->n_right->n_type; + q2 = p->n_right->n_qual; + d = p->n_left->n_df; + d2 = p->n_right->n_df; + ap = p->n_left->n_ap; + ap2 = p->n_right->n_ap; + + switch( o ){ + + case ASSIGN: + case RETURN: + case CAST: + { break; } + + case MINUS: { + int isdyn(struct symtab *sp); + struct symtab s1, s2; + + s1.stype = DECREF(t); + s1.sdf = d; + s2.stype = DECREF(t2); + s2.sdf = d2; + if (isdyn(&s1) || isdyn(&s2)) + ; /* We don't know */ + else if (psize(p->n_left) != psize(p->n_right)) + uerror("illegal pointer subtraction"); + break; + } + + case COLON: + if (t1 != t2) { + /* + * Check for void pointer types. They are allowed + * to cast to/from any pointers. + */ + if (ISPTR(t1) && ISPTR(t2) && + (BTYPE(t1) == VOID || BTYPE(t2) == VOID)) + break; + uerror("illegal types in :"); + } + break; + + default: /* must work harder: relationals or comparisons */ + + if( !ISPTR(t1) ){ + t = t2; + q = q2; + d = d2; + ap = ap2; + break; + } + if( !ISPTR(t2) ){ + break; + } + + /* both are pointers */ + if( talign(t2,ap2) < talign(t,ap) ){ + t = t2; + q = q2; + ap = ap2; + } + break; + } + + p->n_left = makety( p->n_left, t, q, d, ap ); + p->n_right = makety( p->n_right, t, q, d, ap ); + if( o!=MINUS && !clogop(o) ){ + + p->n_type = t; + p->n_qual = q; + p->n_df = d; + p->n_ap = ap; + } + + return(clocal(p)); + } + +int tdebug = 0; + + +/* + * Satisfy the types of various arithmetic binary ops. + * + * rules are: + * if assignment, type of LHS + * if any doubles, make double + * else if any float make float + * else if any longlongs, make long long + * else if any longs, make long + * else etcetc. + * + * If the op with the highest rank is unsigned, this is the resulting type. + * See: 6.3.1.1 rank order equal of signed and unsigned types + * 6.3.1.8 Usual arithmetic conversions + */ +NODE * +tymatch(NODE *p) +{ + TWORD tl, tr, t, tu; + NODE *l, *r; + int o, lu, ru; + + o = p->n_op; + r = p->n_right; + l = p->n_left; + + tl = l->n_type; + tr = r->n_type; + + lu = ru = 0; + if (ISUNSIGNED(tl)) { + lu = 1; + tl = DEUNSIGN(tl); + } + if (ISUNSIGNED(tr)) { + ru = 1; + tr = DEUNSIGN(tr); + } + + if (clogop(o) && tl == tr && lu != ru && + l->n_op != ICON && r->n_op != ICON) + warner(Wsign_compare, NULL); + + if (tl == LDOUBLE || tr == LDOUBLE) + t = LDOUBLE; + else if (tl == DOUBLE || tr == DOUBLE) + t = DOUBLE; + else if (tl == FLOAT || tr == FLOAT) + t = FLOAT; + else if (tl==LONGLONG || tr == LONGLONG) + t = LONGLONG; + else if (tl==LONG || tr==LONG) + t = LONG; + else /* everything else */ + t = INT; + + if (casgop(o)) { + tu = l->n_type; + t = tl; + } else { + /* Should result be unsigned? */ + /* This depends on ctype() being called correctly */ + tu = t; + if (UNSIGNABLE(t) && (lu || ru)) { + if (tl >= tr && lu) + tu = ENUNSIGN(t); + if (tr >= tl && ru) + tu = ENUNSIGN(t); + } + } + + /* because expressions have values that are at least as wide + as INT or UNSIGNED, the only conversions needed + are those involving FLOAT/DOUBLE, and those + from LONG to INT and ULONG to UNSIGNED */ + + if (t != tl || (ru && !lu)) { + if (o != CAST && r->n_op != ICON && + tsize(tl, 0, MKAP(tl)) > tsize(tu, 0, MKAP(tu))) + warner(Wtruncate, tnames[tu], tnames[tl]); + p->n_left = makety( p->n_left, tu, 0, 0, MKAP(tu)); + } + + if (t != tr || o==CAST || (lu && !ru)) { + if (o != CAST && r->n_op != ICON && + tsize(tr, 0, MKAP(tr)) > tsize(tu, 0, MKAP(tu))) + warner(Wtruncate, tnames[tu], tnames[tr]); + p->n_right = makety(p->n_right, tu, 0, 0, MKAP(tu)); + } + + if( casgop(o) ){ + p->n_type = p->n_left->n_type; + p->n_df = p->n_left->n_df; + p->n_ap = p->n_left->n_ap; + } + else if( !clogop(o) ){ + p->n_type = tu; + p->n_df = NULL; + p->n_ap = MKAP(t); + } + +#ifdef PCC_DEBUG + if (tdebug) { + printf("tymatch(%p): ", p); + tprint(stdout, tl, 0); + printf(" %s ", copst(o)); + tprint(stdout, tr, 0); + printf(" => "); + tprint(stdout, tu, 0); + printf("\n"); + fwalk(p, eprint, 0); + } +#endif + + return(p); + } + +/* + * Create a float const node of zero. + */ +static NODE * +fzero(TWORD t) +{ + NODE *p = block(FCON, NIL, NIL, t, 0, MKAP(t)); + + p->n_dcon = FLOAT_CAST(0, INT); + return p; +} + +/* + * make p into type t by inserting a conversion + */ +NODE * +makety(NODE *p, TWORD t, TWORD q, union dimfun *d, struct attr *ap) +{ + + if (t == p->n_type) { + p->n_df = d; + p->n_ap = ap; + p->n_qual = q; + return(p); + } + + if (p->n_op == FCON && (t >= FLOAT && t <= LDOUBLE)) { + if (t == FLOAT) + p->n_dcon = (float)p->n_dcon; + else if (t == DOUBLE) + p->n_dcon = (double)p->n_dcon; + else + p->n_dcon = (long double)p->n_dcon; + p->n_type = t; + return p; + } + + if (p->n_op == FCON) { + int isf = ISFTY(t); + NODE *r; + + if (isf||ISITY(t)) { + if (isf == ISFTY(p->n_type)) { + p->n_type = t; + p->n_qual = q; + p->n_df = d; + p->n_ap = ap; + return(p); + } else if (isf == ISITY(p->n_type)) { + /* will be zero */ + nfree(p); + return fzero(t); + } else if (ISCTY(p->n_type)) + cerror("complex constant"); + } else if (ISCTY(t)) { + if (ISITY(p->n_type)) { + /* convert to correct subtype */ + r = fzero(t - (COMPLEX-DOUBLE)); + p->n_type = t + (IMAG-COMPLEX); + p->n_qual = q; + p->n_df = d; + p->n_ap = MKAP(p->n_type); + return block(CM, r, p, t, 0, MKAP(t)); + } else if (ISFTY(p->n_type)) { + /* convert to correct subtype */ + r = fzero(t + (IMAG-COMPLEX)); + p->n_type = t - (COMPLEX-DOUBLE); + p->n_qual = q; + p->n_df = d; + p->n_ap = MKAP(p->n_type); + return block(CM, p, r, t, 0, MKAP(t)); + } else if (ISCTY(p->n_type)) + cerror("complex constant2"); + } + } + + if (t & TMASK) { + /* non-simple type */ + p = block(PCONV, p, NIL, t, d, ap); + p->n_qual = q; + return clocal(p); + } + + if (p->n_op == ICON) { + if (ISFTY(t)) { + p->n_op = FCON; + p->n_dcon = FLOAT_CAST(p->n_lval, p->n_type); + p->n_type = t; + p->n_qual = q; + p->n_ap = MKAP(t); + return (clocal(p)); + } else if (ISCTY(t) || ISITY(t)) + cerror("complex constant3"); + } + + p = block(SCONV, p, NIL, t, d, ap); + p->n_qual = q; + return clocal(p); + +} + +NODE * +block(int o, NODE *l, NODE *r, TWORD t, union dimfun *d, struct attr *ap) +{ + register NODE *p; + + p = talloc(); + p->n_rval = 0; + p->n_op = o; + p->n_lval = 0; /* Protect against large lval */ + p->n_left = l; + p->n_right = r; + p->n_type = t; + p->n_qual = 0; + p->n_df = d; + p->n_ap = ap; +#if !defined(MULTIPASS) + /* p->n_reg = */p->n_su = 0; + p->n_regw = 0; +#endif + return(p); + } + +/* + * Return the constant value from an ICON. + */ +CONSZ +icons(NODE *p) +{ + /* if p is an integer constant, return its value */ + CONSZ val; + + if (p->n_op != ICON || p->n_sp != NULL) { + uerror( "constant expected"); + val = 1; + } else + val = p->n_lval; + tfree(p); + return(val); +} + +/* + * the intent of this table is to examine the + * operators, and to check them for + * correctness. + * + * The table is searched for the op and the + * modified type (where this is one of the + * types INT (includes char and short), LONG, + * DOUBLE (includes FLOAT), and POINTER + * + * The default action is to make the node type integer + * + * The actions taken include: + * PUN check for puns + * CVTL convert the left operand + * CVTR convert the right operand + * TYPL the type is determined by the left operand + * TYPR the type is determined by the right operand + * TYMATCH force type of left and right to match,by inserting conversions + * PTMATCH like TYMATCH, but for pointers + * LVAL left operand must be lval + * CVTO convert the op + * NCVT do not convert the operands + * OTHER handled by code + * NCVTR convert the left operand, not the right... + * + */ + +# define MINT 01 /* integer */ +# define MDBI 02 /* integer or double */ +# define MSTR 04 /* structure */ +# define MPTR 010 /* pointer */ +# define MPTI 020 /* pointer or integer */ + +int +opact(NODE *p) +{ + int mt12, mt1, mt2, o; + + mt1 = mt2 = mt12 = 0; + + switch (coptype(o = p->n_op)) { + case BITYPE: + mt12=mt2 = moditype(p->n_right->n_type); + case UTYPE: + mt12 &= (mt1 = moditype(p->n_left->n_type)); + break; + } + + switch( o ){ + + case NAME : + case ICON : + case FCON : + case CALL : + case UCALL: + case UMUL: + { return( OTHER ); } + case UMINUS: + if( mt1 & MDBI ) return( TYPL ); + break; + + case COMPL: + if( mt1 & MINT ) return( TYPL ); + break; + + case ADDROF: + return( NCVT+OTHER ); + case NOT: +/* case INIT: */ + case CM: + case CBRANCH: + case ANDAND: + case OROR: + return( 0 ); + + case MUL: + case DIV: + if( mt12 & MDBI ) return( TYMATCH ); + break; + + case MOD: + case AND: + case OR: + case ER: + if( mt12 & MINT ) return( TYMATCH ); + break; + + case LS: + case RS: + if( mt12 & MINT ) return( TYPL+OTHER ); + break; + + case EQ: + case NE: + case LT: + case LE: + case GT: + case GE: + if( mt12 & MDBI ) return( TYMATCH+CVTO ); + else if( mt12 & MPTR ) return( PTMATCH+PUN+CVTO ); + else if( mt12 & MPTI ) return( PTMATCH+PUN ); + else break; + + case QUEST: + return( TYPR+OTHER ); + case COMOP: + return( TYPR ); + + case STREF: + return( NCVTR+OTHER ); + + case FORCE: + return( TYPL ); + + case COLON: + if( mt12 & MDBI ) return( TYMATCH ); + else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN ); + else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN ); + else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN ); + else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER ); + break; + + case ASSIGN: + case RETURN: + if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER ); + case CAST: + if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH ); + else if( mt1 & MPTR) return( LVAL+PTMATCH+PUN ); + else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN ); + break; + + case LSEQ: + case RSEQ: + if( mt12 & MINT ) return( TYPL+LVAL+OTHER ); + break; + + case MULEQ: + case DIVEQ: + if( mt12 & MDBI ) return( LVAL+TYMATCH ); + break; + + case MODEQ: + case ANDEQ: + case OREQ: + case EREQ: + if (mt12 & MINT) + return(LVAL+TYMATCH); + break; + + case PLUSEQ: + case MINUSEQ: + case INCR: + case DECR: + if (mt12 & MDBI) + return(TYMATCH+LVAL); + else if ((mt1&MPTR) && (mt2&MINT)) + return(TYPL+LVAL+CVTR); + break; + + case MINUS: + if (mt12 & MPTR) + return(CVTO+PTMATCH+PUN); + if (mt2 & MPTR) + break; + /* FALLTHROUGH */ + case PLUS: + if (mt12 & MDBI) + return(TYMATCH); + else if ((mt1&MPTR) && (mt2&MINT)) + return(TYPL+CVTR); + else if ((mt1&MINT) && (mt2&MPTR)) + return(TYPR+CVTL); + + } + uerror("operands of %s have incompatible types", copst(o)); + return(NCVT); +} + +int +moditype(TWORD ty) +{ + switch (ty) { + + case STRTY: + case UNIONTY: + return( MSTR ); + + case BOOL: + case CHAR: + case SHORT: + case UCHAR: + case USHORT: + case UNSIGNED: + case ULONG: + case ULONGLONG: + case INT: + case LONG: + case LONGLONG: + return( MINT|MDBI|MPTI ); + case FLOAT: + case DOUBLE: + case LDOUBLE: +#ifndef NO_COMPLEX + case FCOMPLEX: + case COMPLEX: + case LCOMPLEX: + case FIMAG: + case IMAG: + case LIMAG: +#endif + return( MDBI ); + default: + return( MPTR|MPTI ); + + } +} + +int tvaloff = MAXREGS+NPERMREG > 100 ? MAXREGS+NPERMREG + 100 : 100; + +/* + * Returns a TEMP node with temp number nr. + * If nr == 0, return a node with a new number. + */ +NODE * +tempnode(int nr, TWORD type, union dimfun *df, struct attr *ap) +{ + NODE *r; + + if (tvaloff == -NOOFFSET) + tvaloff++; /* Skip this for array indexing */ + r = block(TEMP, NIL, NIL, type, df, ap); + regno(r) = nr ? nr : tvaloff; + tvaloff += szty(type); + return r; +} + +/* + * Do sizeof on p. + */ +NODE * +doszof(NODE *p) +{ + extern NODE *arrstk[10]; + extern int arrstkp; + union dimfun *df; + TWORD ty; + NODE *rv, *q; + int astkp; + + if (p->n_op == FLD) + uerror("can't apply sizeof to bit-field"); + + /* + * Arrays may be dynamic, may need to make computations. + */ + + rv = bcon(1); + df = p->n_df; + ty = p->n_type; + astkp = 0; + while (ISARY(ty)) { + if (df->ddim == NOOFFSET) + uerror("sizeof of incomplete type"); + if (df->ddim < 0) { + if (arrstkp) + q = arrstk[astkp++]; + else + q = tempnode(-df->ddim, INT, 0, MKAP(INT)); + } else + q = bcon(df->ddim); + rv = buildtree(MUL, rv, q); + df++; + ty = DECREF(ty); + } + rv = buildtree(MUL, rv, bcon(tsize(ty, p->n_df, p->n_ap)/SZCHAR)); + tfree(p); + arrstkp = 0; /* XXX - may this fail? */ + return rv; +} + +#ifdef PCC_DEBUG +void +eprint(NODE *p, int down, int *a, int *b) +{ + int ty; + + *a = *b = down+1; + while( down > 1 ){ + printf( "\t" ); + down -= 2; + } + if( down ) printf( " " ); + + ty = coptype( p->n_op ); + + printf("%p) %s, ", p, copst(p->n_op)); + if (p->n_op == XARG || p->n_op == XASM) + printf("id '%s', ", p->n_name); + if (ty == LTYPE) { + printf(CONFMT, p->n_lval); + if (p->n_op == NAME || p->n_op == ICON) + printf(", %p, ", p->n_sp); + else + printf(", %d, ", p->n_rval); + } + tprint(stdout, p->n_type, p->n_qual); + printf( ", %p, ", p->n_df); + dump_attr(p->n_ap); +} +# endif + +/* + * Emit everything that should be emitted on the left side + * of a comma operator, and remove the operator. + * Do not traverse through QUEST, ANDAND and OROR. + * Enable this for all targets when stable enough. + */ +static void +comops(NODE *p) +{ + int o; + NODE *q; + + while (p->n_op == COMOP) { + /* XXX hack for GCC ({ }) ops */ + if (p->n_left->n_op == GOTO) { + int v = (int)p->n_left->n_left->n_lval; + ecomp(p->n_left); + plabel(v+1); + } else + ecomp(p->n_left); /* will recurse if more COMOPs */ + q = p->n_right; + *p = *q; + nfree(q); + } + o = coptype(p->n_op); + if (p->n_op == QUEST || p->n_op == ANDAND || p->n_op == OROR) + o = UTYPE; + if (o != LTYPE) + comops(p->n_left); + if (o == BITYPE) + comops(p->n_right); +} + +/* + * Walk up through the tree from the leaves, + * removing constant operators. + */ +static void +logwalk(NODE *p) +{ + int o = coptype(p->n_op); + NODE *l, *r; + + l = p->n_left; + r = p->n_right; + switch (o) { + case LTYPE: + return; + case BITYPE: + logwalk(r); + case UTYPE: + logwalk(l); + } + if (!clogop(p->n_op)) + return; + if (p->n_op == NOT && l->n_op == ICON) { + p->n_lval = l->n_lval == 0; + nfree(l); + p->n_op = ICON; + } + if (l->n_op == ICON && r->n_op == ICON) { + if (conval(l, p->n_op, r) == 0) { + /* + * people sometimes tend to do really odd compares, + * like "if ("abc" == "def")" etc. + * do it runtime instead. + */ + } else { + p->n_lval = l->n_lval; + p->n_op = ICON; + nfree(l); + nfree(r); + } + } +} + +/* + * Removes redundant logical operators for branch conditions. + */ +static void +fixbranch(NODE *p, int label) +{ + + logwalk(p); + + if (p->n_op == ICON) { + if (p->n_lval != 0) + branch(label); + nfree(p); + } else { + if (!clogop(p->n_op)) /* Always conditional */ + p = buildtree(NE, p, bcon(0)); + ecode(buildtree(CBRANCH, p, bcon(label))); + } +} + +/* + * Write out logical expressions as branches. + */ +static void +andorbr(NODE *p, int true, int false) +{ + NODE *q; + int o, lab; + + lab = -1; + switch (o = p->n_op) { + case EQ: + case NE: + /* + * Remove redundant EQ/NE nodes. + */ + while (((o = p->n_left->n_op) == EQ || o == NE) && + p->n_right->n_op == ICON) { + o = p->n_op; + q = p->n_left; + if (p->n_right->n_lval == 0) { + nfree(p->n_right); + *p = *q; + nfree(q); + if (o == EQ) + p->n_op = negrel[p->n_op - EQ]; +#if 0 + p->n_op = NE; /* toggla */ +#endif + } else if (p->n_right->n_lval == 1) { + nfree(p->n_right); + *p = *q; + nfree(q); + if (o == NE) + p->n_op = negrel[p->n_op - EQ]; +#if 0 + p->n_op = EQ; /* toggla */ +#endif + } else + break; /* XXX - should always be false */ + + } + /* FALLTHROUGH */ + case LE: + case LT: + case GE: + case GT: +calc: if (true < 0) { + p->n_op = negrel[p->n_op - EQ]; + true = false; + false = -1; + } + + rmcops(p->n_left); + rmcops(p->n_right); + fixbranch(p, true); + if (false >= 0) + branch(false); + break; + + case ULE: + case UGT: + /* Convert to friendlier ops */ + if (p->n_right->n_op == ICON && p->n_right->n_lval == 0) + p->n_op = o == ULE ? EQ : NE; + goto calc; + + case UGE: + case ULT: + /* Already true/false by definition */ + if (p->n_right->n_op == ICON && p->n_right->n_lval == 0) { + if (true < 0) { + o = o == ULT ? UGE : ULT; + true = false; + } + rmcops(p->n_left); + ecode(p->n_left); + rmcops(p->n_right); + ecode(p->n_right); + nfree(p); + if (o == UGE) /* true */ + branch(true); + break; + } + goto calc; + + case ANDAND: + lab = false<0 ? getlab() : false ; + andorbr(p->n_left, -1, lab); + comops(p->n_right); + andorbr(p->n_right, true, false); + if (false < 0) + plabel( lab); + nfree(p); + break; + + case OROR: + lab = true<0 ? getlab() : true; + andorbr(p->n_left, lab, -1); + comops(p->n_right); + andorbr(p->n_right, true, false); + if (true < 0) + plabel( lab); + nfree(p); + break; + + case NOT: + andorbr(p->n_left, false, true); + nfree(p); + break; + + default: + rmcops(p); + if (true >= 0) + fixbranch(p, true); + if (false >= 0) { + if (true >= 0) + branch(false); + else + fixbranch(buildtree(EQ, p, bcon(0)), false); + } + } +} + +/* + * Create a node for either TEMP or on-stack storage. + */ +static NODE * +cstknode(TWORD t, union dimfun *df, struct attr *ap) +{ + struct symtab *sp; + + /* create a symtab entry suitable for this type */ + sp = getsymtab("0hej", STEMP); + sp->stype = t; + sp->sdf = df; + sp->sap = ap; + sp->sclass = AUTO; + sp->soffset = NOOFFSET; + oalloc(sp, &autooff); + return nametree(sp); + +} + +/* + * Massage the output trees to remove C-specific nodes: + * COMOPs are split into separate statements. + * QUEST/COLON are rewritten to branches. + * ANDAND/OROR/NOT are rewritten to branches for lazy-evaluation. + * CBRANCH conditions are rewritten for lazy-evaluation. + */ +static void +rmcops(NODE *p) +{ + TWORD type; + NODE *q, *r, *tval; + int o, ty, lbl, lbl2; + + tval = NIL; + o = p->n_op; + ty = coptype(o); + if (BTYPE(p->n_type) == ENUMTY) { /* fixup enum */ + struct symtab *sp = strmemb(p->n_ap); + MODTYPE(p->n_type, sp->stype); + /* + * XXX may fail if these are true: + * - variable-sized enums + * - non-byte-addressed targets. + */ + if (BTYPE(p->n_type) == ENUMTY && ISPTR(p->n_type)) + MODTYPE(p->n_type, INT); /* INT ok? */ + } + switch (o) { + case QUEST: + + /* + * Create a branch node from ?: + * || and && must be taken special care of. + */ + type = p->n_type; + andorbr(p->n_left, -1, lbl = getlab()); + + /* Make ASSIGN node */ + /* Only if type is not void */ + q = p->n_right->n_left; + comops(q); + if (type != VOID) { + tval = cstknode(q->n_type, q->n_df, q->n_ap); + q = buildtree(ASSIGN, ccopy(tval), q); + } + rmcops(q); + ecode(q); /* Done with assign */ + branch(lbl2 = getlab()); + plabel( lbl); + + q = p->n_right->n_right; + comops(q); + if (type != VOID) { + q = buildtree(ASSIGN, ccopy(tval), q); + } + rmcops(q); + ecode(q); /* Done with assign */ + + plabel( lbl2); + + nfree(p->n_right); + if (p->n_type != VOID) { + *p = *tval; + nfree(tval); + } else { + p->n_op = ICON; + p->n_lval = 0; + p->n_sp = NULL; + } + break; + + case ULE: + case ULT: + case UGE: + case UGT: + case EQ: + case NE: + case LE: + case LT: + case GE: + case GT: + case ANDAND: + case OROR: + case NOT: +#ifdef SPECIAL_CCODES +#error fix for private CCODES handling +#else + r = talloc(); + *r = *p; + andorbr(r, -1, lbl = getlab()); + + tval = cstknode(p->n_type, p->n_df, p->n_ap); + + ecode(buildtree(ASSIGN, ccopy(tval), bcon(1))); + branch(lbl2 = getlab()); + plabel( lbl); + ecode(buildtree(ASSIGN, ccopy(tval), bcon(0))); + plabel( lbl2); + + *p = *tval; + nfree(tval); + +#endif + break; + case CBRANCH: + andorbr(p->n_left, p->n_right->n_lval, -1); + nfree(p->n_right); + p->n_op = ICON; p->n_type = VOID; + break; + case COMOP: + cerror("COMOP error"); + + default: + if (ty == LTYPE) + return; + rmcops(p->n_left); + if (ty == BITYPE) + rmcops(p->n_right); + } +} + +/* + * Return 1 if an assignment is found. + */ +static int +has_se(NODE *p) +{ + if (cdope(p->n_op) & ASGFLG) + return 1; + if (coptype(p->n_op) == LTYPE) + return 0; + if (has_se(p->n_left)) + return 1; + if (coptype(p->n_op) == BITYPE) + return has_se(p->n_right); + return 0; +} + +/* + * Find and convert asgop's to separate statements. + * Be careful about side effects. + * assign tells whether ASSIGN should be considered giving + * side effects or not. + */ +static NODE * +delasgop(NODE *p) +{ + NODE *q, *r; + int tval; + + if (p->n_op == INCR || p->n_op == DECR) { + /* + * Rewrite x++ to (x += 1) -1; and deal with it further down. + * Pass2 will remove -1 if unnecessary. + */ + q = ccopy(p); + tfree(p->n_left); + q->n_op = (p->n_op==INCR)?PLUSEQ:MINUSEQ; + p->n_op = (p->n_op==INCR)?MINUS:PLUS; + p->n_left = delasgop(q); + + } else if ((cdope(p->n_op)&ASGOPFLG) && + p->n_op != RETURN && p->n_op != CAST) { + NODE *l = p->n_left; + NODE *ll = l->n_left; + + if (has_se(l)) { + q = tempnode(0, ll->n_type, ll->n_df, ll->n_ap); + tval = regno(q); + r = tempnode(tval, ll->n_type, ll->n_df,ll->n_ap); + l->n_left = q; + /* Now the left side of node p has no side effects. */ + /* side effects on the right side must be obeyed */ + p = delasgop(p); + + r = buildtree(ASSIGN, r, ll); + r = delasgop(r); + ecode(r); + } else { +#if 0 /* Cannot call buildtree() here, it would invoke double add shifts */ + p->n_right = buildtree(UNASG p->n_op, ccopy(l), + p->n_right); +#else + p->n_right = block(UNASG p->n_op, ccopy(l), + p->n_right, p->n_type, p->n_df, p->n_ap); +#endif + p->n_op = ASSIGN; + p->n_right = delasgop(p->n_right); + p->n_right = clocal(p->n_right); + } + + } else { + if (coptype(p->n_op) == LTYPE) + return p; + p->n_left = delasgop(p->n_left); + if (coptype(p->n_op) == BITYPE) + p->n_right = delasgop(p->n_right); + } + return p; +} + +int edebug = 0; +void +ecomp(NODE *p) +{ + +#ifdef PCC_DEBUG + if (edebug) + fwalk(p, eprint, 0); +#endif + if (!reached) { + warner(Wunreachable_code, NULL); + reached = 1; + } + p = optim(p); + comops(p); + rmcops(p); + p = delasgop(p); + if (p->n_op == ICON && p->n_type == VOID) + tfree(p); + else + ecode(p); +} + + +#if defined(MULTIPASS) +void +p2tree(NODE *p) +{ + struct symtab *q; + int ty; + + myp2tree(p); /* local action can be taken here */ + + ty = coptype(p->n_op); + + printf("%d\t", p->n_op); + + if (ty == LTYPE) { + printf(CONFMT, p->n_lval); + printf("\t"); + } + if (ty != BITYPE) { + if (p->n_op == NAME || p->n_op == ICON) + printf("0\t"); + else + printf("%d\t", p->n_rval); + } + + printf("%o\t", p->n_type); + + /* handle special cases */ + + switch (p->n_op) { + + case NAME: + case ICON: + /* print external name */ + if ((q = p->n_sp) != NULL) { + if ((q->sclass == STATIC && q->slevel > 0)) { + printf(LABFMT, q->soffset); + } else + printf("%s\n", + q->soname ? q->soname : exname(q->sname)); + } else + printf("\n"); + break; + + case STARG: + case STASG: + case STCALL: + case USTCALL: + /* print out size */ + /* use lhs size, in order to avoid hassles + * with the structure `.' operator + */ + + /* note: p->left not a field... */ + printf(CONFMT, (CONSZ)tsize(STRTY, p->n_left->n_df, + p->n_left->n_ap)); + printf("\t%d\t\n", talign(STRTY, p->n_left->n_ap)); + break; + + case XARG: + case XASM: + break; + + default: + printf( "\n" ); + } + + if (ty != LTYPE) + p2tree(p->n_left); + if (ty == BITYPE) + p2tree(p->n_right); +} +#else +static char * +sptostr(struct symtab *sp) +{ + char *cp = inlalloc(32); + int n = sp->soffset; + if (n < 0) + n = -n; + snprintf(cp, 32, LABFMT, n); + return cp; +} + +void +p2tree(NODE *p) +{ + struct symtab *q; + int ty; + + myp2tree(p); /* local action can be taken here */ + + /* Fix left imaginary types */ + if (ISITY(BTYPE(p->n_type))) + MODTYPE(p->n_type, p->n_type - (FIMAG-FLOAT)); + + ty = coptype(p->n_op); + + switch( p->n_op ){ + + case NAME: + case ICON: + if ((q = p->n_sp) != NULL) { + if ((q->sclass == STATIC && q->slevel > 0) +#ifdef GCC_COMPAT + || q->sflags == SLBLNAME +#endif + ) { + p->n_name = sptostr(q); + } else { + if ((p->n_name = q->soname) == NULL) + p->n_name = addname(exname(q->sname)); + } + } else + p->n_name = ""; + break; + + case STASG: + /* STASG used for stack array init */ + if (ISARY(p->n_type)) { + int size1 = (int)tsize(p->n_type, p->n_left->n_df, + p->n_left->n_ap)/SZCHAR; + p->n_stsize = (int)tsize(p->n_type, p->n_right->n_df, + p->n_right->n_ap)/SZCHAR; + if (size1 < p->n_stsize) + p->n_stsize = size1; + p->n_stalign = talign(p->n_type, + p->n_left->n_ap)/SZCHAR; + break; + } + /* FALLTHROUGH */ + case STARG: + case STCALL: + case USTCALL: + /* set up size parameters */ + p->n_stsize = (int)((tsize(STRTY, p->n_left->n_df, + p->n_left->n_ap)+SZCHAR-1)/SZCHAR); + p->n_stalign = talign(STRTY,p->n_left->n_ap)/SZCHAR; + if (p->n_stalign == 0) + p->n_stalign = 1; /* At least char for packed structs */ + break; + + case XARG: + case XASM: + break; + + default: + p->n_name = ""; + } + + if( ty != LTYPE ) p2tree( p->n_left ); + if( ty == BITYPE ) p2tree( p->n_right ); + } + +#endif + +/* + * Change void data types into char. + */ +static void +delvoid(NODE *p, void *arg) +{ + /* Convert "PTR undef" (void *) to "PTR uchar" */ + if (BTYPE(p->n_type) == VOID) + p->n_type = (p->n_type & ~BTMASK) | UCHAR; + if (BTYPE(p->n_type) == BOOL) { + if (p->n_op == SCONV && p->n_type == BOOL) { + /* create a jump and a set */ + NODE *r; + int l, l2; + + r = tempnode(0, BOOL_TYPE, NULL, MKAP(BOOL_TYPE)); + cbranch(buildtree(EQ, p->n_left, bcon(0)), + bcon(l = getlab())); + *p = *r; + ecode(buildtree(ASSIGN, tcopy(r), bcon(1))); + branch(l2 = getlab()); + plabel(l); + ecode(buildtree(ASSIGN, r, bcon(0))); + plabel(l2); + } else + p->n_type = (p->n_type & ~BTMASK) | BOOL_TYPE; + } + +} + +void +ecode(NODE *p) +{ + /* walk the tree and write out the nodes.. */ + + if (nerrors) + return; + +#ifdef GCC_COMPAT + { + NODE *q = p; + + if (q->n_op == UMUL) + q = p->n_left; + if (cdope(q->n_op)&CALLFLG && + attr_find(q->n_ap, GCC_ATYP_WARN_UNUSED_RESULT)) + werror("return value ignored"); + } +#endif + p = optim(p); + p = delasgop(p); + walkf(p, delvoid, 0); +#ifdef PCC_DEBUG + if (xdebug) { + printf("Fulltree:\n"); + fwalk(p, eprint, 0); + } +#endif + p2tree(p); +#if !defined(MULTIPASS) + send_passt(IP_NODE, p); +#endif +} + +/* + * Send something further on to the next pass. + */ +void +send_passt(int type, ...) +{ + struct interpass *ip; + struct interpass_prolog *ipp; + extern int crslab; + va_list ap; + int sz; + + va_start(ap, type); + if (cftnsp == NULL && type != IP_ASM) { +#ifdef notyet + cerror("no function"); +#endif + if (type == IP_NODE) + tfree(va_arg(ap, NODE *)); + return; + } + if (type == IP_PROLOG || type == IP_EPILOG) + sz = sizeof(struct interpass_prolog); + else + sz = sizeof(struct interpass); + + ip = inlalloc(sz); + ip->type = type; + ip->lineno = lineno; + switch (type) { + case IP_NODE: + ip->ip_node = va_arg(ap, NODE *); + break; + case IP_EPILOG: + if (!isinlining) + defloc(cftnsp); + /* FALLTHROUGH */ + case IP_PROLOG: + inftn = type == IP_PROLOG ? 1 : 0; + ipp = (struct interpass_prolog *)ip; + memset(ipp->ipp_regs, (type == IP_PROLOG)? -1 : 0, + sizeof(ipp->ipp_regs)); + ipp->ipp_autos = va_arg(ap, int); + ipp->ipp_name = va_arg(ap, char *); + ipp->ipp_type = va_arg(ap, TWORD); + ipp->ipp_vis = va_arg(ap, int); + ip->ip_lbl = va_arg(ap, int); + ipp->ip_tmpnum = va_arg(ap, int); + ipp->ip_lblnum = crslab; + if (type == IP_PROLOG) + ipp->ip_lblnum--; + break; + case IP_DEFLAB: + ip->ip_lbl = va_arg(ap, int); + break; + case IP_ASM: + if (blevel == 0) { /* outside function */ + printf("\t"); + printf("%s", va_arg(ap, char *)); + printf("\n"); + va_end(ap); + defloc(NULL); + return; + } + ip->ip_asm = va_arg(ap, char *); + break; + default: + cerror("bad send_passt type %d", type); + } + va_end(ap); + pass1_lastchance(ip); /* target-specific info */ + if (isinlining) + inline_addarg(ip); + else + pass2_compile(ip); +} + +char * +copst(int op) +{ + if (op <= MAXOP) + return opst[op]; +#define SNAM(x,y) case x: return #y; + switch (op) { + SNAM(QUALIFIER,QUALIFIER) + SNAM(CLASS,CLASS) + SNAM(RB,]) + SNAM(DOT,.) + SNAM(ELLIPSIS,...) + SNAM(LB,[) + SNAM(TYPE,TYPE) + SNAM(COMOP,COMOP) + SNAM(QUEST,?) + SNAM(COLON,:) + SNAM(ANDAND,&&) + SNAM(OROR,||) + SNAM(NOT,!) + SNAM(CAST,CAST) + SNAM(PLUSEQ,+=) + SNAM(MINUSEQ,-=) + SNAM(MULEQ,*=) + SNAM(DIVEQ,/=) + SNAM(MODEQ,%=) + SNAM(ANDEQ,&=) + SNAM(OREQ,|=) + SNAM(EREQ,^=) + SNAM(LSEQ,<<=) + SNAM(RSEQ,>>=) + SNAM(INCR,++) + SNAM(DECR,--) + SNAM(STRING,STRING) + SNAM(SZOF,SIZEOF) + SNAM(ATTRIB,ATTRIBUTE) + SNAM(TYMERGE,TYMERGE) +#ifdef GCC_COMPAT + SNAM(XREAL,__real__) + SNAM(XIMAG,__imag__) +#endif + default: + cerror("bad copst %d", op); + } + return 0; /* XXX gcc */ +} + +int +cdope(int op) +{ + if (op <= MAXOP) + return dope[op]; + switch (op) { + case CLOP: + case STRING: + case QUALIFIER: + case CLASS: + case RB: + case ELLIPSIS: + case TYPE: + return LTYPE; + case DOT: + case SZOF: + case COMOP: + case QUEST: + case COLON: + case LB: + case TYMERGE: + return BITYPE; + case XIMAG: + case XREAL: + case ATTRIB: + return UTYPE; + case ANDAND: + case OROR: + return BITYPE|LOGFLG; + case NOT: + return UTYPE|LOGFLG; + case CAST: + return BITYPE|ASGFLG|ASGOPFLG; + case PLUSEQ: + return BITYPE|ASGFLG|ASGOPFLG|FLOFLG|SIMPFLG|COMMFLG; + case MINUSEQ: + return BITYPE|FLOFLG|SIMPFLG|ASGFLG|ASGOPFLG; + case MULEQ: + return BITYPE|FLOFLG|MULFLG|ASGFLG|ASGOPFLG; + case OREQ: + case EREQ: + case ANDEQ: + return BITYPE|SIMPFLG|COMMFLG|ASGFLG|ASGOPFLG; + case DIVEQ: + return BITYPE|FLOFLG|MULFLG|DIVFLG|ASGFLG|ASGOPFLG; + case MODEQ: + return BITYPE|DIVFLG|ASGFLG|ASGOPFLG; + case LSEQ: + case RSEQ: + return BITYPE|SHFFLG|ASGFLG|ASGOPFLG; + case INCR: + case DECR: + return BITYPE|ASGFLG; + } + cerror("cdope missing op %d", op); + return 0; /* XXX gcc */ +} + +/* + * make a fresh copy of p + */ +NODE * +ccopy(NODE *p) +{ + NODE *q; + + q = talloc(); + *q = *p; + + switch (coptype(q->n_op)) { + case BITYPE: + q->n_right = ccopy(p->n_right); + case UTYPE: + q->n_left = ccopy(p->n_left); + } + + return(q); +} + +/* + * set PROG-seg label. + */ +void +plabel(int label) +{ + reached = 1; /* Will this always be correct? */ + send_passt(IP_DEFLAB, label); +} + +/* + * Perform integer promotion on node n. + */ +NODE * +intprom(NODE *n) +{ + if ((n->n_type >= CHAR && n->n_type < INT) || n->n_type == BOOL) { + if ((n->n_type == UCHAR && MAX_UCHAR > MAX_INT) || + (n->n_type == USHORT && MAX_USHORT > MAX_INT)) + return makety(n, UNSIGNED, 0, 0, MKAP(UNSIGNED)); + return makety(n, INT, 0, 0, MKAP(INT)); + } + return n; +} + +/* + * Return CON/VOL/0, whichever are active for the current type. + */ +int +cqual(TWORD t, TWORD q) +{ + while (ISARY(t)) + t = DECREF(t), q = DECQAL(q); + if (t <= BTMASK) + q <<= TSHIFT; + return q & (CON|VOL); +} + +int crslab = 10; +/* + * Return a number for internal labels. + */ +int +getlab(void) +{ + return crslab++; +} diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/CVS/Entries b/compilers/pcc/pcc-1.0.0/cc/cpp/CVS/Entries new file mode 100644 index 00000000..ca75557b --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/CVS/Entries @@ -0,0 +1,9 @@ +/Makefile.in/1.30/Sun Jan 16 11:59:37 2011//Tr-1-0-0-RELEASE +/cpp.1/1.11/Mon Apr 5 13:13:57 2010//Tr-1-0-0-RELEASE +/cpp.c/1.124.2.2/Sun Mar 27 13:17:19 2011//Tr-1-0-0-RELEASE +/cpp.h/1.47.2.1/Sat Feb 26 06:36:40 2011//Tr-1-0-0-RELEASE +/cpy.y/1.18/Thu Feb 25 15:49:00 2010//Tr-1-0-0-RELEASE +/scanner.l/1.49/Sat Feb 14 09:23:55 2009//Tr-1-0-0-RELEASE +/token.c/1.48.2.2/Sat Mar 12 17:08:26 2011//Tr-1-0-0-RELEASE +D/tests//// +D diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/CVS/Repository b/compilers/pcc/pcc-1.0.0/cc/cpp/CVS/Repository new file mode 100644 index 00000000..9fd1d1f8 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/CVS/Repository @@ -0,0 +1 @@ +pcc/cc/cpp diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/CVS/Root b/compilers/pcc/pcc-1.0.0/cc/cpp/CVS/Root new file mode 100644 index 00000000..71e2ccb9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/CVS/Root @@ -0,0 +1 @@ +/cvsroot diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/CVS/Tag b/compilers/pcc/pcc-1.0.0/cc/cpp/CVS/Tag new file mode 100644 index 00000000..060fac05 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/CVS/Tag @@ -0,0 +1 @@ +Nr-1-0-0-RELEASE diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/Makefile.in b/compilers/pcc/pcc-1.0.0/cc/cpp/Makefile.in new file mode 100644 index 00000000..e03bfdb9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/Makefile.in @@ -0,0 +1,105 @@ +# $Id: Makefile.in,v 1.30 2011/01/16 11:59:37 ragge Exp $ +# +# Makefile.in for cpp +# +VPATH=@srcdir@ +srcdir=@srcdir@ +top_srcdir=@top_srcdir@ +builddir=@builddir@ +top_builddir=@top_builddir@ +XFL=-DCPP_DEBUG + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libexecdir = @libexecdir@ +datarootdir = @datarootdir@ +mandir = @mandir@ +strip = @strip@ +CC = @CC@ +EXEEXT = @EXEEXT@ +CFLAGS = @CFLAGS@ @ADD_CFLAGS@ +CPPFLAGS = @CPPFLAGS@ @ADD_CPPFLAGS@ ${XFL} -I${srcdir} -I${top_builddir} -I${builddir} -I${MIPDIR} -I${MDIR} +LIBS = @LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +YACC = @YACC@ +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +TARGMACH = @targmach@ + +OBJS=cpp.o cpy.o token.o compat.o +HEADERS=cpp.h +DEST=@BINPREFIX@cpp$(EXEEXT) + +MIPDIR=$(top_srcdir)/mip +MDIR=$(top_srcdir)/arch/$(TARGMACH) + +all: ${DEST} + +${DEST}: $(OBJS) $(HEADERS) + $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@ + +.c.o: + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c $< + +.l.o: + $(LEX) $(LFLAGS) $< + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ lex.yy.c + +.y.o: + $(YACC) -d $(YFLAGS) $< + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ y.tab.c + +compat.o: $(MIPDIR)/compat.c + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/compat.c + +$(OBJS): $(HEADERS) + +cpp.o: cpy.o +token.o: cpy.o + +test: + ./cpp < tests/test1 > tests/run1 + cmp tests/run1 tests/res1 + ./cpp < tests/test2 > tests/run2 + cmp tests/run2 tests/res2 + ./cpp < tests/test3 > tests/run3 + cmp tests/run3 tests/res3 + ./cpp < tests/test4 > tests/run4 + cmp tests/run4 tests/res4 + ./cpp < tests/test5 > tests/run5 + cmp tests/run5 tests/res5 + ./cpp < tests/test6 > tests/run6 + cmp tests/run6 tests/res6 + ./cpp < tests/test7 > tests/run7 + cmp tests/run7 tests/res7 + ./cpp < tests/test8 > tests/run8 + cmp tests/run8 tests/res8 + ./cpp < tests/test9 > tests/run9 + cmp tests/run9 tests/res9 + ./cpp < tests/test10 > tests/run10 + cmp tests/run10 tests/res10 + ./cpp < tests/test11 > tests/run11 + cmp tests/run11 tests/res11 + ./cpp < tests/test12 > tests/run12 + cmp tests/run12 tests/res12 + ./cpp < tests/test13 > tests/run13 + cmp tests/run13 tests/res13 + + +install: + test -z "${DESTDIR}$(libexecdir)" || mkdir -p "${DESTDIR}$(libexecdir)" + ${INSTALL_PROGRAM} ${DEST} ${DESTDIR}${libexecdir} + @if [ ${strip} = yes ]; then \ + strip ${DESTDIR}${libexecdir}/${DEST} ; \ + echo strip ${DESTDIR}${libexecdir}/${DEST} ; \ + fi + test -z "${DESTDIR}$(mandir)/man1" || mkdir -p "${DESTDIR}$(mandir)/man1" + ${INSTALL} $(srcdir)/cpp.1 ${DESTDIR}${mandir}/man1/$(DEST).1 + +clean: + /bin/rm -f $(OBJS) $(DEST) lex.yy.c y.tab.[ch] tests/run* + +distclean: clean + /bin/rm -f Makefile diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/cpp.1 b/compilers/pcc/pcc-1.0.0/cc/cpp/cpp.1 new file mode 100644 index 00000000..fdf23a54 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/cpp.1 @@ -0,0 +1,210 @@ +.\" $Id: cpp.1,v 1.11 2010/04/05 13:13:57 reed Exp $ +.\" $NetBSD$ +.\" $OpenBSD$ +.\" +.\" Copyright (c) 2007 Jeremy C. Reed +.\" +.\" Permission to use, copy, modify, and/or distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR AND CONTRIBUTORS DISCLAIM +.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHOR AND +.\" CONTRIBUTORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +.\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +.\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +.\" THIS SOFTWARE. +.\" +.Dd September 17, 2007 +.Dt CPP 1 +.Os +.Sh NAME +.Nm cpp +.Nd C preprocessor +.Sh SYNOPSIS +.Nm +.\" TODO also document -Dvar and below without spaces? +.Op Fl CdMtVv +.Op Fl D Ar macro[=value] +.Op Fl I Ar path +.Op Fl i Ar file +.Op Fl S Ar path +.Op Fl U Ar macro +.Op Ar infile | - +.Op Ar outfile +.Sh DESCRIPTION +The +.Nm +utility is a macro preprocessor used by the +.Xr pcc 1 +compiler. +It is used to include header files, +expand macro definitions, +and perform conditional compilation. +.Pp +The +.Ar infile +input file is optional. +If not provided or the file name is +.Qq - +(dash), +.Nm +reads its initial file from standard input. +The +.Ar outfile +output file is also optional. +It writes by default to standard output. +.Pp +.\" TODO: document MAXARG 250 args to a macro, limited by char value +.\" TODO: Include order: +.\" For "..." files, first search "current" dir, then as <...> files. +.\" For <...> files, first search -I directories, then system directories. +.\" +The options are as follows: +.Bl -tag -width Ds +.It Fl ? +Show command line usage for +.Nm . +.It Fl C +Do not discard comments. +.It Fl D Ar macro[=value] +Fake a definition at the beginning by using +.Do #define +.Ar macro=value Dc . +If +.Ar value +is not set on command-line, then define it as 1. +.\" TODO: show example +.It Fl dM +Print list of +.Dq #define +statements to standard output for all defined macros other than +builtin macros (see below). +The normal results of preprocessing are not output. +.\" TODO this doesn't show predefined macros +.\" other -d options are ignored +.It Fl I Ar path +Add +.Ar path +to the list of directories containing needed header files. +This may be used to override system include directories +(see +.Fl S +option). +.Fl I +may be specified multiple times. +.It Fl i Ar file +Include a file at the beginning by using +.Do #include +.Ar file Dc . +.\" Note: I did not use the .In macro above +.It Fl M +Generate dependencies for +.Xr make 1 . +.\" TODO: explain and show example? +.It Fl P +Inhibit generation of line markers. This is sometimes useful when +running the preprocessor on something other than C code. +.It Fl S Ar path +Add +.Ar path +to the list of system directories containing needed header files. +The +.Fl S +option may be specified multiple times. +Note: +.Nm +does not have a default include directory defined. +.\" TODO: explain difference between -I and -S +.\" The directories listed by -I are searched first? +.It Fl t +Traditional cpp syntax. +Do not define the +.Dv __TIME__ , +.Dv __DATE__ , +.Dv __STDC__ , +and +.Dv __STDC_VERSION__ +macros. +.\" +.It Fl U Ar macro +Undefine a macro at the beginning by using +.Do #undef +.Ar macro Dc . +.It Fl V +Verbose debugging output. +.Fl V +can be repeated for further details. +.\" -V only available if cpp source built with CPP_DEBUG, which is the default. +.It Fl v +Display version. +.El +.Ss Builtin Macros +A few macros are interpreted inside the +.Nm cpp +program: +.Bl -diag +.It __DATE__ +Expands to the date in abbreviated month, day, and year format from +.Xr ctime 3 +in quotes. +.\" TODO: is that ctime(3) format output change according to locale? +.It __FILE__ +Expands to the name of the current input file in quotes. +When read from standard input, it expands to +.Qq Aq stdin . +.It __LINE__ +Expands to the line number of the current line containing the macro. +.It __STDC__ +Expands to the constant 1. +This means the compiler conforms to +.St -isoC +.Po also known as +.Do C90 Dc Pc . +.It __STDC_VERSION__ +Expands to +.Dq 199901L +which indicates that +.Nm +supports +.St -isoC-99 +.Po commonly referred to as +.Do C99 Dc Pc . +.It __TIME__ +Expands to the time in hour, minutes, and seconds from +.Xr ctime 3 +in quotes. +.El +.Pp +Also see the +.Fl t +option. +.Sh EXIT STATUS +The +.Nm +utility exits with one of the following values: +.Bl -tag -width Ds +.It 0 +Successfully finished. +.It 1 +An error occurred. +.El +.Sh SEE ALSO +.Xr as 1 , +.Xr ccom 1 , +.Xr pcc 1 +.\" +.Sh HISTORY +The +.Nm +command comes from the original Portable C Compiler by S. C. Johnson, +written in the late 70's. +The code originates from the V6 preprocessor with some additions +from V7 cpp and ansi/c99 support. +.Pp +A lot of the PCC code was rewritten by Anders Magnusson. +.Pp +This product includes software developed or owned by Caldera +International, Inc. diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/cpp.c b/compilers/pcc/pcc-1.0.0/cc/cpp/cpp.c new file mode 100644 index 00000000..1d186acf --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/cpp.c @@ -0,0 +1,1971 @@ +/* $Id: cpp.c,v 1.124.2.2 2011/03/27 13:17:19 ragge Exp $ */ + +/* + * Copyright (c) 2004,2010 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * The C preprocessor. + * This code originates from the V6 preprocessor with some additions + * from V7 cpp, and at last ansi/c99 support. + */ + +#include "config.h" + +#ifdef HAVE_SYS_WAIT_H +#include +#endif +#include + +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#include +#include + +#include "compat.h" +#include "cpp.h" +#include "y.tab.h" + +#define SBSIZE 1000000 + +static usch sbf[SBSIZE]; +/* C command */ + +int tflag; /* traditional cpp syntax */ +#ifdef CPP_DEBUG +int dflag; /* debug printouts */ +#define DPRINT(x) if (dflag) printf x +#define DDPRINT(x) if (dflag > 1) printf x +#else +#define DPRINT(x) +#define DDPRINT(x) +#endif + +int ofd; +usch outbuf[CPPBUF]; +int obufp, istty; +int Cflag, Mflag, dMflag, Pflag; +usch *Mfile; +struct initar *initar; +int readmac, lastoch; + +/* include dirs */ +struct incs { + struct incs *next; + usch *dir; + dev_t dev; + ino_t ino; +} *incdir[2]; +#define INCINC 0 +#define SYSINC 1 + +static struct symtab *filloc; +static struct symtab *linloc; +static struct symtab *pragloc; +int trulvl; +int flslvl; +int elflvl; +int elslvl; +usch *stringbuf = sbf; + +/* + * Macro replacement list syntax: + * - For object-type macros, replacement strings are stored as-is. + * - For function-type macros, macro args are substituted for the + * character WARN followed by the argument number. + * - The value element points to the end of the string, to simplify + * pushback onto the input queue. + * + * The first character (from the end) in the replacement list is + * the number of arguments: + * VARG - ends with ellipsis, next char is argcount without ellips. + * OBJCT - object-type macro + * 0 - empty parenthesis, foo() + * 1-> - number of args. + * + * WARN is used: + * - in stored replacement lists to tell that an argument comes + * - When expanding replacement lists to tell that the list ended. + * + * To ensure that an already expanded identifier won't get expanded + * again a EBLOCK char + its number is stored directly before any + * expanded identifier. + */ + +/* args for lookup() */ +#define FIND 0 +#define ENTER 1 + +static int readargs(struct symtab *sp, const usch **args); +void prline(const usch *s); +static void prrep(const usch *s); +static void exparg(int); +static void subarg(struct symtab *sp, const usch **args, int); +void define(void); +void include(void); +void include_next(void); +void line(void); +void flbuf(void); +void usage(void); +usch *xstrdup(const usch *str); +static void addidir(char *idir, struct incs **ww); +void imp(const char *); +#define IMP(x) if (dflag>1) imp(x) + +int +main(int argc, char **argv) +{ + struct initar *it; + struct symtab *nl; + register int ch; + const usch *fn1, *fn2; + +#ifdef TIMING + struct timeval t1, t2; + + (void)gettimeofday(&t1, NULL); +#endif + + while ((ch = getopt(argc, argv, "CD:I:MPS:U:d:i:tvV?")) != -1) + switch (ch) { + case 'C': /* Do not discard comments */ + Cflag++; + break; + + case 'i': /* include */ + case 'U': /* undef */ + case 'D': /* define something */ + /* XXX should not need malloc() here */ + if ((it = malloc(sizeof(struct initar))) == NULL) + error("couldn't apply -%c %s", ch, optarg); + it->type = ch; + it->str = optarg; + it->next = initar; + initar = it; + break; + + case 'M': /* Generate dependencies for make */ + Mflag++; + break; + + case 'P': /* Inhibit generation of line numbers */ + Pflag++; + break; + + case 'S': + case 'I': + addidir(optarg, &incdir[ch == 'I' ? INCINC : SYSINC]); + break; + +#ifdef CPP_DEBUG + case 'V': + dflag++; + break; +#endif + case 'v': + printf("cpp: %s\n", VERSSTR); + break; + case 'd': + if (optarg[0] == 'M') { + dMflag = 1; + Mflag = 1; + } + /* ignore others */ + break; + + case 't': + tflag = 1; + break; + + case '?': + usage(); + default: + error("bad arg %c\n", ch); + } + argc -= optind; + argv += optind; + + filloc = lookup((const usch *)"__FILE__", ENTER); + linloc = lookup((const usch *)"__LINE__", ENTER); + filloc->value = linloc->value = stringbuf; + savch(OBJCT); + + /* create a complete macro for pragma */ + pragloc = lookup((const usch *)"_Pragma", ENTER); + savch(0); + savstr((const usch *)"_Pragma("); + savch(0); + savch(WARN); + savch(')'); + pragloc->value = stringbuf; + savch(1); + + if (tflag == 0) { + time_t t = time(NULL); + usch *n = (usch *)ctime(&t); + + /* + * Manually move in the predefined macros. + */ + nl = lookup((const usch *)"__TIME__", ENTER); + savch(0); savch('"'); n[19] = 0; savstr(&n[11]); savch('"'); + savch(OBJCT); + nl->value = stringbuf-1; + + nl = lookup((const usch *)"__DATE__", ENTER); + savch(0); savch('"'); n[24] = n[11] = 0; savstr(&n[4]); + savstr(&n[20]); savch('"'); savch(OBJCT); + nl->value = stringbuf-1; + + nl = lookup((const usch *)"__STDC__", ENTER); + savch(0); savch('1'); savch(OBJCT); + nl->value = stringbuf-1; + + nl = lookup((const usch *)"__STDC_VERSION__", ENTER); + savch(0); savstr((const usch *)"199901L"); savch(OBJCT); + nl->value = stringbuf-1; + } + + if (Mflag && !dMflag) { + usch *c; + + if (argc < 1) + error("-M and no infile"); + if ((c = (usch *)strrchr(argv[0], '/')) == NULL) + c = (usch *)argv[0]; + else + c++; + Mfile = stringbuf; + savstr(c); savch(0); + if ((c = (usch *)strrchr((char *)Mfile, '.')) == NULL) + error("-M and no extension: "); + c[1] = 'o'; + c[2] = 0; + } + + if (argc == 2) { + if ((ofd = open(argv[1], O_WRONLY|O_CREAT, 0600)) < 0) + error("Can't creat %s", argv[1]); + } else + ofd = 1; /* stdout */ + istty = isatty(ofd); + + if (argc && strcmp(argv[0], "-")) { + fn1 = fn2 = (usch *)argv[0]; + } else { + fn1 = NULL; + fn2 = (const usch *)""; + } + if (pushfile(fn1, fn2, 0, NULL)) + error("cannot open %s", argv[0]); + + flbuf(); + close(ofd); +#ifdef TIMING + (void)gettimeofday(&t2, NULL); + t2.tv_sec -= t1.tv_sec; + t2.tv_usec -= t1.tv_usec; + if (t2.tv_usec < 0) { + t2.tv_usec += 1000000; + t2.tv_sec -= 1; + } + fprintf(stderr, "cpp total time: %ld s %ld us\n", + t2.tv_sec, t2.tv_usec); +#endif + return 0; +} + +static void +addidir(char *idir, struct incs **ww) +{ + struct incs *w; + struct stat st; + + if (stat(idir, &st) == -1 || S_ISDIR(st.st_mode) == 0) + return; /* ignore */ + if (*ww != NULL) { + for (w = *ww; w->next; w = w->next) { + if (w->dev == st.st_dev && w->ino == st.st_ino) + return; + } + if (w->dev == st.st_dev && w->ino == st.st_ino) + return; + ww = &w->next; + } + if ((w = calloc(sizeof(struct incs), 1)) == NULL) + error("couldn't add path %s", idir); + w->dir = (usch *)idir; + w->dev = st.st_dev; + w->ino = st.st_ino; + *ww = w; +} + +void +line() +{ + static usch *lbuf; + static int llen; + usch *p; + int c; + + if ((c = yylex()) != NUMBER) + goto bad; + ifiles->lineno = (int)(yylval.node.nd_val - 1); + + if ((c = yylex()) == '\n') + return; + + if (c != STRING) + goto bad; + + p = (usch *)yytext; + if (*p == 'L') + p++; + c = strlen((char *)p); + if (llen < c) { + /* XXX may loose heap space */ + lbuf = stringbuf; + stringbuf += c; + llen = c; + } + p[strlen((char *)p)-1] = 0; + if (strlcpy((char *)lbuf, (char *)&p[1], SBSIZE) >= SBSIZE) + error("line exceeded buffer size"); + + ifiles->fname = lbuf; + if (yylex() == '\n') + return; + +bad: error("bad line directive"); +} + +/* + * Search for and include next file. + * Return 1 on success. + */ +static int +fsrch(const usch *fn, int idx, struct incs *w) +{ + int i; + + for (i = idx; i < 2; i++) { + if (i > idx) + w = incdir[i]; + for (; w; w = w->next) { + usch *nm = stringbuf; + + savstr(w->dir); savch('/'); + savstr(fn); savch(0); + if (pushfile(nm, fn, i, w->next) == 0) + return 1; + stringbuf = nm; + } + } + return 0; +} + +/* + * Include a file. Include order: + * - For <...> files, first search -I directories, then system directories. + * - For "..." files, first search "current" dir, then as <...> files. + */ +void +include() +{ + struct symtab *nl; + usch *osp; + usch *fn, *safefn; + int c, it; + + if (flslvl) + return; + osp = stringbuf; + + while ((c = sloscan()) == WSPACE) + ; + if (c == IDENT) { + /* sloscan() will not expand idents */ + if ((nl = lookup((usch *)yytext, FIND)) == NULL) + goto bad; + if (kfind(nl)) + unpstr(stringbuf); + else + unpstr(nl->namep); + stringbuf = osp; + c = yylex(); + } + if (c != STRING && c != '<') + goto bad; + + if (c == '<') { + fn = stringbuf; + while ((c = sloscan()) != '>' && c != '\n') { + if (c == '\n') /* XXX check - cannot reach */ + goto bad; + savstr((usch *)yytext); + } + savch('\0'); + while ((c = sloscan()) == WSPACE) + ; + if (c != '\n') + goto bad; + it = SYSINC; + safefn = fn; + } else { + usch *nm = stringbuf; + + yytext[strlen((char *)yytext)-1] = 0; + fn = (usch *)&yytext[1]; + /* first try to open file relative to previous file */ + /* but only if it is not an absolute path */ + if (*fn != '/') { + savstr(ifiles->orgfn); + if ((stringbuf = + (usch *)strrchr((char *)nm, '/')) == NULL) + stringbuf = nm; + else + stringbuf++; + } + safefn = stringbuf; + savstr(fn); savch(0); + c = yylex(); + if (c != '\n') + goto bad; + if (pushfile(nm, safefn, 0, NULL) == 0) + goto okret; + /* XXX may loose stringbuf space */ + } + + if (fsrch(safefn, 0, incdir[0])) + goto okret; + + error("cannot find '%s'", safefn); + /* error() do not return */ + +bad: error("bad include"); + /* error() do not return */ +okret: + prtline(); +} + +void +include_next() +{ + struct symtab *nl; + usch *osp; + usch *fn; + int c; + + if (flslvl) + return; + osp = stringbuf; + while ((c = sloscan()) == WSPACE) + ; + if (c == IDENT) { + /* sloscan() will not expand idents */ + if ((nl = lookup((usch *)yytext, FIND)) == NULL) + goto bad; + if (kfind(nl)) + unpstr(stringbuf); + else + unpstr(nl->namep); + stringbuf = osp; + c = yylex(); + } + if (c != STRING && c != '<') + goto bad; + + fn = stringbuf; + if (c == STRING) { + savstr((usch *)&yytext[1]); + stringbuf[-1] = 0; + } else { /* < > */ + while ((c = sloscan()) != '>') { + if (c == '\n') + goto bad; + savstr((usch *)yytext); + } + savch('\0'); + } + while ((c = sloscan()) == WSPACE) + ; + if (c != '\n') + goto bad; + + if (fsrch(fn, ifiles->idx, ifiles->incs) == 0) + error("cannot find '%s'", fn); + prtline(); + return; + +bad: error("bad include"); + /* error() do not return */ +} + +static int +definp(void) +{ + int c; + + do + c = sloscan(); + while (c == WSPACE); + return c; +} + +void +getcmnt(void) +{ + int c; + + savstr((usch *)yytext); + savch(cinput()); /* Lost * */ + for (;;) { + c = cinput(); + if (c == '*') { + c = cinput(); + if (c == '/') { + savstr((const usch *)"*/"); + return; + } + cunput(c); + c = '*'; + } + savch(c); + } +} + +/* + * Compare two replacement lists, taking in account comments etc. + */ +static int +cmprepl(const usch *o, const usch *n) +{ + for (; *o; o--, n--) { + /* comment skip */ + if (*o == '/' && o[-1] == '*') { + while (*o != '*' || o[-1] != '/') + o--; + o -= 2; + } + if (*n == '/' && n[-1] == '*') { + while (*n != '*' || n[-1] != '/') + n--; + n -= 2; + } + while (*o == ' ' || *o == '\t') + o--; + while (*n == ' ' || *n == '\t') + n--; + if (*o != *n) + return 1; + } + return 0; +} + +static int +isell(void) +{ + int ch; + + if ((ch = cinput()) != '.') { + cunput(ch); + return 0; + } + if ((ch = cinput()) != '.') { + cunput(ch); + cunput('.'); + return 0; + } + return 1; +} + +void +define() +{ + struct symtab *np; + usch *args[MAXARGS+1], *ubuf, *sbeg; + int c, i, redef; + int mkstr = 0, narg = -1; + int ellips = 0; +#ifdef GCC_COMPAT + usch *gccvari = NULL; + int wascon; +#endif + + if (flslvl) + return; + if (sloscan() != WSPACE || sloscan() != IDENT) + goto bad; + + if (isdigit((int)yytext[0])) + goto bad; + + np = lookup((usch *)yytext, ENTER); + redef = np->value != NULL; + + readmac = 1; + sbeg = stringbuf; + if ((c = sloscan()) == '(') { + narg = 0; + /* function-like macros, deal with identifiers */ + c = definp(); + for (;;) { + if (c == ')') + break; + if (c == '.' && isell()) { + ellips = 1; + if (definp() != ')') + goto bad; + break; + } + if (c == IDENT) { + /* make sure there is no arg of same name */ + for (i = 0; i < narg; i++) + if (!strcmp((char *) args[i], (char *)yytext)) + error("Duplicate macro " + "parameter \"%s\"", yytext); + if (narg == MAXARGS) + error("Too many macro args"); + args[narg++] = xstrdup(yytext); + if ((c = definp()) == ',') { + if ((c = definp()) == ')') + goto bad; + continue; + } +#ifdef GCC_COMPAT + if (c == '.' && isell()) { + if (definp() != ')') + goto bad; + gccvari = args[--narg]; + break; + } +#endif + if (c == ')') + break; + } + goto bad; + } + c = sloscan(); + } else if (c == '\n') { + /* #define foo */ + ; + } else if (c != WSPACE) + goto bad; + + while (c == WSPACE) + c = sloscan(); + + /* replacement list cannot start with ## operator */ + if (c == '#') { + if ((c = sloscan()) == '#') + goto bad; + savch('\0'); +#ifdef GCC_COMPAT + wascon = 0; +#endif + goto in2; + } + + /* parse replacement-list, substituting arguments */ + savch('\0'); + while (c != '\n') { +#ifdef GCC_COMPAT + wascon = 0; +loop: +#endif + switch (c) { + case WSPACE: + /* remove spaces if it surrounds a ## directive */ + ubuf = stringbuf; + savstr((usch *)yytext); + c = sloscan(); + if (c == '#') { + if ((c = sloscan()) != '#') + goto in2; + stringbuf = ubuf; + savch(CONC); + if ((c = sloscan()) == WSPACE) + c = sloscan(); +#ifdef GCC_COMPAT + if (c == '\n') + break; + wascon = 1; + goto loop; +#endif + } + continue; + + case '#': + c = sloscan(); + if (c == '#') { + /* concat op */ + savch(CONC); + if ((c = sloscan()) == WSPACE) + c = sloscan(); +#ifdef GCC_COMPAT + if (c == '\n') + break; + wascon = 1; + goto loop; +#else + continue; +#endif + } +in2: if (narg < 0) { + /* no meaning in object-type macro */ + savch('#'); + continue; + } + /* remove spaces between # and arg */ + savch(SNUFF); + if (c == WSPACE) + c = sloscan(); /* whitespace, ignore */ + mkstr = 1; + if (c == IDENT && strcmp((char *)yytext, "__VA_ARGS__") == 0) + continue; + + /* FALLTHROUGH */ + case IDENT: + if (strcmp((char *)yytext, "__VA_ARGS__") == 0) { + if (ellips == 0) + error("unwanted %s", yytext); +#ifdef GCC_COMPAT + savch(wascon ? GCCARG : VARG); +#else + savch(VARG); +#endif + + savch(WARN); + if (mkstr) + savch(SNUFF), mkstr = 0; + break; + } + if (narg < 0) + goto id; /* just add it if object */ + /* check if its an argument */ + for (i = 0; i < narg; i++) + if (strcmp((char *)yytext, (char *)args[i]) == 0) + break; + if (i == narg) { +#ifdef GCC_COMPAT + if (gccvari && + strcmp((char *)yytext, (char *)gccvari) == 0) { + savch(wascon ? GCCARG : VARG); + savch(WARN); + if (mkstr) + savch(SNUFF), mkstr = 0; + break; + } +#endif + if (mkstr) + error("not argument"); + goto id; + } + savch(i); + savch(WARN); + if (mkstr) + savch(SNUFF), mkstr = 0; + break; + + case CMNT: /* save comments */ + getcmnt(); + break; + + default: +id: savstr((usch *)yytext); + break; + } + c = sloscan(); + } + readmac = 0; + /* remove trailing whitespace */ + while (stringbuf > sbeg) { + if (stringbuf[-1] == ' ' || stringbuf[-1] == '\t') + stringbuf--; + /* replacement list cannot end with ## operator */ + else if (stringbuf[-1] == CONC) + goto bad; + else + break; + } +#ifdef GCC_COMPAT + if (gccvari) { + savch(narg); + savch(VARG); + } else +#endif + if (ellips) { + savch(narg); + savch(VARG); + } else + savch(narg < 0 ? OBJCT : narg); + if (redef && ifiles->idx != SYSINC) { + if (cmprepl(np->value, stringbuf-1)) { + sbeg = stringbuf; + np->value = stringbuf-1; + warning("%s redefined\nprevious define: %s:%d", + np->namep, np->file, np->line); + } + stringbuf = sbeg; /* forget this space */ + } else + np->value = stringbuf-1; + +#ifdef CPP_DEBUG + if (dflag) { + const usch *w = np->value; + + printf("!define: "); + if (*w == OBJCT) + printf("[object]"); + else if (*w == VARG) + printf("[VARG%d]", *--w); + while (*--w) { + switch (*w) { + case WARN: printf("<%d>", *--w); break; + case CONC: printf("<##>"); break; + case SNUFF: printf("<\">"); break; + default: putchar(*w); break; + } + } + putchar('\n'); + } +#endif + for (i = 0; i < narg; i++) + free(args[i]); + return; + +bad: error("bad define"); +} + +void +xwarning(usch *s) +{ + usch *t; + usch *sb = stringbuf; + int dummy; + + flbuf(); + savch(0); + if (ifiles != NULL) { + t = sheap("%s:%d: warning: ", ifiles->fname, ifiles->lineno); + write (2, t, strlen((char *)t)); + } + dummy = write (2, s, strlen((char *)s)); + dummy = write (2, "\n", 1); + stringbuf = sb; +} + +void +xerror(usch *s) +{ + usch *t; + int dummy; + + flbuf(); + savch(0); + if (ifiles != NULL) { + t = sheap("%s:%d: error: ", ifiles->fname, ifiles->lineno); + dummy = write (2, t, strlen((char *)t)); + } + dummy = write (2, s, strlen((char *)s)); + dummy = write (2, "\n", 1); + exit(1); +} + +static void +sss(void) +{ + savch(EBLOCK); + savch(cinput()); + savch(cinput()); +} + +static int +addmac(struct symtab *sp) +{ + int c, i; + + /* Check if it exists; then save some space */ + /* May be more difficult to debug cpp */ + for (i = 1; i < norepptr; i++) + if (norep[i] == sp) + return i; + if (norepptr >= RECMAX) + error("too many macros"); + /* check norepptr */ + if ((norepptr & 255) == 0) + norepptr++; + if (((norepptr >> 8) & 255) == 0) + norepptr += 256; + c = norepptr; + norep[norepptr++] = sp; + return c; +} + +static void +doblk(void) +{ + int c; + + do { + donex(); + } while ((c = sloscan()) == EBLOCK); + if (c != IDENT) + error("EBLOCK sync error"); +} + +/* Block next nr in lex buffer to expand */ +int +donex(void) +{ + int n, i; + + if (bidx == RECMAX) + error("too deep macro recursion"); + n = cinput(); + n = MKB(n, cinput()); + for (i = 0; i < bidx; i++) + if (bptr[i] == n) + return n; /* already blocked */ + bptr[bidx++] = n; + /* XXX - check for sp buffer overflow */ + if (dflag>1) { + printf("donex %d (%d) blocking:\n", bidx, n); + printf("donex %s(%d) blocking:", norep[n]->namep, n); + for (i = bidx-1; i >= 0; i--) + printf(" '%s'", norep[bptr[i]]->namep); + printf("\n"); + } + return n; +} + +/* + * store a character into the "define" buffer. + */ +void +savch(int c) +{ + if (stringbuf-sbf < SBSIZE) { + *stringbuf++ = (usch)c; + } else { + stringbuf = sbf; /* need space to write error message */ + error("Too much defining"); + } +} + +/* + * convert _Pragma to #pragma for output. + * Syntax is already correct. + */ +static void +pragoper(void) +{ + usch *s; + int t; + + while ((t = sloscan()) != '(') + ; + + while ((t = sloscan()) == WSPACE) + ; + if (t != STRING) + error("pragma must have string argument"); + savstr((const usch *)"\n#pragma "); + s = (usch *)yytext; + if (*s == 'L') + s++; + for (; *s; s++) { + if (*s == '\"') + continue; + if (*s == '\\' && (s[1] == '\"' || s[1] == '\\')) + s++; + savch(*s); + } + sheap("\n# %d \"%s\"\n", ifiles->lineno, ifiles->fname); + while ((t = sloscan()) == WSPACE) + ; + if (t != ')') + error("pragma syntax error"); +} + +/* + * Return true if it is OK to expand this symbol. + */ +static int +okexp(struct symtab *sp) +{ + int i; + + if (sp == NULL) + return 0; + for (i = 0; i < bidx; i++) + if (norep[bptr[i]] == sp) + return 0; + return 1; +} + +/* + * Insert block(s) before each expanded name. + * Input is in lex buffer, output on lex buffer. + */ +static void +insblock(int bnr) +{ + usch *bp = stringbuf; + int c, i; + + IMP("IB"); + while ((c = sloscan()) != WARN) { + if (c == EBLOCK) { + sss(); + continue; + } + if (c == IDENT) { + savch(EBLOCK), savch(bnr & 255), savch(bnr >> 8); + for (i = 0; i < bidx; i++) + savch(EBLOCK), savch(bptr[i] & 255), + savch(bptr[i] >> 8); + } + savstr((const usch *)yytext); + if (c == '\n') + (void)cinput(); + } + savch(0); + cunput(WARN); + unpstr(bp); + stringbuf = bp; + IMP("IBRET"); +} + +/* Delete next WARN on the input stream */ +static void +delwarn(void) +{ + usch *bp = stringbuf; + int c; + + IMP("DELWARN"); + while ((c = sloscan()) != WARN) { + if (c == EBLOCK) { + sss(); + } else + savstr(yytext); + } + savch(0); + unpstr(bp); + stringbuf = bp; + IMP("DELWRET"); +} + +/* + * Handle defined macro keywords found on input stream. + * When finished print out the full expanded line. + * Everything on lex buffer except for the symtab. + */ +int +kfind(struct symtab *sp) +{ + struct symtab *nl; + const usch *argary[MAXARGS+1], *cbp; + usch *sbp; + int c, o, chkf; + + DPRINT(("%d:enter kfind(%s)\n",0,sp->namep)); + IMP("KFIND"); + if (*sp->value == OBJCT) { + if (sp == filloc) { + unpstr(sheap("\"%s\"", ifiles->fname)); + return 1; + } else if (sp == linloc) { + unpstr(sheap("%d", ifiles->lineno)); + return 1; + } + IMP("END1"); + cunput(WARN); + for (cbp = sp->value-1; *cbp; cbp--) + cunput(*cbp); + insblock(addmac(sp)); + IMP("ENDX"); + exparg(1); + +upp: sbp = stringbuf; + chkf = 1; + if (obufp != 0) + lastoch = outbuf[obufp-1]; + if (iswsnl(lastoch)) + chkf = 0; + while ((c = sloscan()) != WARN) { + switch (c) { + case STRING: + /* Remove embedded directives */ + for (cbp = (usch *)yytext; *cbp; cbp++) { + if (*cbp == EBLOCK) + cbp+=2; + else if (*cbp != CONC) + savch(*cbp); + } + break; + + case EBLOCK: + doblk(); + /* FALLTHROUGH */ + case IDENT: + /* + * Tricky: if this is the last identifier + * in the expanded list, and it is defined + * as a function-like macro, then push it + * back on the input stream and let fastscan + * handle it as a new macro. + * BUT: if this macro is blocked then this + * should not be done. + */ + nl = lookup((usch *)yytext, FIND); + o = okexp(nl); + bidx = 0; + /* Deal with pragmas here */ + if (nl == pragloc) { + pragoper(); + break; + } + if (nl == NULL || !o || *nl->value == OBJCT) { + /* Not fun-like macro */ + savstr(yytext); + break; + } + c = cinput(); + if (c == WARN) { + /* succeeded, push back */ + unpstr(yytext); + } else { + savstr(yytext); + } + cunput(c); + break; + + default: + if (chkf && c < 127) + putch(' '); + savstr(yytext); + break; + } + chkf = 0; + } + IMP("END2"); + norepptr = 1; + savch(0); + stringbuf = sbp; + return 1; + } + /* Is a function-like macro */ + + /* Search for '(' */ + sbp = stringbuf; + while (iswsnl(c = cinput())) + savch(c); + savch(0); + stringbuf = sbp; + if (c != '(') { + cunput(c); + unpstr(sbp); + return 0; /* Failed */ + } + + /* Found one, output \n to be in sync */ + for (; *sbp; sbp++) { + if (*sbp == '\n') + putch('\n'), ifiles->lineno++; + } + + /* fetch arguments */ + if (readargs(sp, argary)) + error("readargs"); + + c = addmac(sp); + sbp = stringbuf; + cunput(WARN); + + IMP("KEXP"); + subarg(sp, argary, 1); + IMP("KNEX"); + insblock(c); + IMP("KBLK"); + + stringbuf = sbp; + + exparg(1); + + IMP("END"); + + goto upp; + +} + +/* + * Replace and push-back on input stream the eventual replaced macro. + * The check for whether it can expand or not should already have been done. + * Blocks for this identifier will be added via insblock() after expansion. + */ +int +submac(struct symtab *sp, int lvl) +{ + const usch *argary[MAXARGS+1]; + const usch *cp; + usch *bp; + int ch; + + DPRINT(("%d:submac1: trying '%s'\n", lvl, sp->namep)); + if (*sp->value == OBJCT) { + if (sp == filloc) { + unpstr(sheap("\"%s\"", ifiles->fname)); + return 1; + } else if (sp == linloc) { + unpstr(sheap("%d", ifiles->lineno)); + return 1; + } + + DPRINT(("submac: exp object macro '%s'\n",sp->namep)); + /* expand object-type macros */ + ch = addmac(sp); + cunput(WARN); + + for (cp = sp->value-1; *cp; cp--) + cunput(*cp); + insblock(ch); + delwarn(); + return 1; + } + + /* + * Function-like macro; see if it is followed by a ( + * Be careful about the expand/noexpand balance. + * Store read data on heap meanwhile. + * For directive #define foo() kaka + * If input is foo() then + * output should be kaka. + */ + bp = stringbuf; + while (iswsnl(ch = cinput())) + savch(ch); + savch(0); + stringbuf = bp; + if (ch != '(') { + cunput(ch); + unpstr(bp); + return 0; /* Failed */ + } + + /* no \n should be here */ + + /* + * A function-like macro has been found. Read in the arguments, + * expand them and push-back everything for another scan. + */ + DPRINT(("%d:submac: continue macro '%s'\n", lvl, sp->namep)); + savch(0); + if (readargs(sp, argary)) { + /* Bailed out in the middle of arg list */ + unpstr(bp); + if (dflag>1)printf("%d:noreadargs\n", lvl); + stringbuf = bp; + return 0; + } + + /* when all args are read from input stream */ + ch = addmac(sp); + + DDPRINT(("%d:submac pre\n", lvl)); + cunput(WARN); + + subarg(sp, argary, lvl+1); + + DDPRINT(("%d:submac post\n", lvl)); + insblock(ch); + delwarn(); + + stringbuf = bp; /* Reset heap */ + DPRINT(("%d:Return submac\n", lvl)); + IMP("SM1"); + return 1; +} + +/* + * Read arguments and put in argument array. + * If WARN is encountered return 1, otherwise 0. + */ +int +readargs(struct symtab *sp, const usch **args) +{ + const usch *vp = sp->value; + int c, i, plev, narg, ellips = 0; + int warn; + + DPRINT(("readargs\n")); + + narg = *vp--; + if (narg == VARG) { + narg = *vp--; + ellips = 1; + } + + IMP("RDA1"); + /* + * read arguments and store them on heap. + */ + warn = 0; + c = '('; + for (i = 0; i < narg && c != ')'; i++) { + args[i] = stringbuf; + plev = 0; + while ((c = sloscan()) == WSPACE || c == '\n') + if (c == '\n') + putch(cinput()); + for (;;) { + while (c == EBLOCK) { + sss(); + c = sloscan(); + } + if (c == WARN) { + warn++; + goto oho; + } + if (plev == 0 && (c == ')' || c == ',')) + break; + if (c == '(') + plev++; + if (c == ')') + plev--; + savstr((usch *)yytext); +oho: while ((c = sloscan()) == '\n') { + putch(cinput()); + savch(' '); + } + while (c == CMNT) { + getcmnt(); + c = sloscan(); + } + if (c == 0) + error("eof in macro"); + } + while (args[i] < stringbuf && + iswsnl(stringbuf[-1]) && stringbuf[-3] != EBLOCK) + stringbuf--; + savch('\0'); + if (dflag) { + printf("readargs: save arg %d '", i); + prline(args[i]); + printf("'\n"); + } + } + + IMP("RDA2"); + /* Handle varargs readin */ + if (ellips) + args[i] = (const usch *)""; + if (ellips && c != ')') { + args[i] = stringbuf; + plev = 0; + while ((c = sloscan()) == WSPACE) + ; + for (;;) { + if (plev == 0 && c == ')') + break; + if (c == '(') + plev++; + if (c == ')') + plev--; + if (c == EBLOCK) { + sss(); + } else + savstr((usch *)yytext); + while ((c = sloscan()) == '\n') { + cinput(); + savch(' '); + } + } + while (args[i] < stringbuf && iswsnl(stringbuf[-1])) + stringbuf--; + savch('\0'); + + } + if (narg == 0 && ellips == 0) + while ((c = sloscan()) == WSPACE || c == '\n') + if (c == '\n') + cinput(); + + if (c != ')' || (i != narg && ellips == 0) || (i < narg && ellips == 1)) + error("wrong arg count"); + while (warn) + cunput(WARN), warn--; + return 0; +} + +#if 0 +/* + * Maybe an indentifier (for macro expansion). + */ +static int +mayid(usch *s) +{ + for (; *s; s++) + if (!isdigit(*s) && !isalpha(*s) && *s != '_') + return 0; + return 1; +} +#endif + +/* + * expand a function-like macro. + * vp points to end of replacement-list + * reads function arguments from sloscan() + * result is pushed-back for more scanning. + */ +void +subarg(struct symtab *nl, const usch **args, int lvl) +{ + int narg, instr, snuff; + const usch *sp, *bp, *ap, *vp; + + DPRINT(("%d:subarg '%s'\n", lvl, nl->namep)); + vp = nl->value; + narg = *vp--; + if (narg == VARG) + narg = *vp--; + + sp = vp; + instr = snuff = 0; + if (dflag>1) { + printf("%d:subarg ARGlist for %s: '", lvl, nl->namep); + prrep(vp); + printf("'\n"); + } + + /* + * push-back replacement-list onto lex buffer while replacing + * arguments. Arguments are macro-expanded if required. + */ + while (*sp != 0) { + if (*sp == SNUFF) + cunput('\"'), snuff ^= 1; + else if (*sp == CONC) + ; + else if (*sp == WARN) { + + if (sp[-1] == VARG) { + bp = ap = args[narg]; + sp--; +#ifdef GCC_COMPAT + } else if (sp[-1] == GCCARG) { + ap = args[narg]; + if (ap[0] == 0) + ap = (const usch *)"0"; + bp = ap; + sp--; +#endif + } else + bp = ap = args[(int)*--sp]; + if (dflag>1){ + printf("%d:subarg GOTwarn; arglist '", lvl); + prline(bp); + printf("'\n"); + } + if (sp[2] != CONC && !snuff && sp[-1] != CONC) { + /* + * Expand an argument; 6.10.3.1: + * "A parameter in the replacement list, + * is replaced by the corresponding argument + * after all macros contained therein have + * been expanded.". + */ + cunput(WARN); + unpstr(bp); + exparg(lvl+1); + delwarn(); + } else { + while (*bp) + bp++; + while (bp > ap) { + bp--; + if (snuff && !instr && iswsnl(*bp)) { + while (iswsnl(*bp)) + bp--; + cunput(' '); + } + + cunput(*bp); + if ((*bp == '\'' || *bp == '"') + && bp[-1] != '\\' && snuff) { + instr ^= 1; + if (instr == 0 && *bp == '"') + cunput('\\'); + } + if (instr && (*bp == '\\' || *bp == '"')) + cunput('\\'); + } + } + } else + cunput(*sp); + sp--; + } + DPRINT(("%d:Return subarg\n", lvl)); + IMP("SUBARG"); +} + +/* + * Do a (correct) expansion of a WARN-terminated buffer of tokens. + * Data is read from the lex buffer, result on lex buffer, WARN-terminated. + * Expansion blocking is not altered here unless when tokens are + * concatenated, in which case they are removed. + */ +void +exparg(int lvl) +{ + struct symtab *nl; + int c, i; + usch *och; + usch *osb = stringbuf; + int anychange; + + DPRINT(("%d:exparg\n", lvl)); + IMP("EXPARG"); + + readmac++; +rescan: + anychange = 0; + while ((c = sloscan()) != WARN) { + DDPRINT(("%d:exparg swdata %d\n", lvl, c)); + IMP("EA0"); + switch (c) { + + case EBLOCK: + doblk(); + /* FALLTHROUGH */ + case IDENT: + /* + * Handle argument concatenation here. + * In case of concatenation, scratch all blockings. + */ + DDPRINT(("%d:exparg ident %d\n", lvl, c)); + och = stringbuf; + +sav: savstr(yytext); + + if ((c = cinput()) == EBLOCK) { + /* yep, are concatenating; forget blocks */ + do { + (void)cinput(); + (void)cinput(); + } while ((c = sloscan()) == EBLOCK); + bidx = 0; + goto sav; + } + cunput(c); + + DPRINT(("%d:exparg: str '%s'\n", lvl, och)); + IMP("EA1"); + /* see if ident is expandable */ + if ((nl = lookup(och, FIND)) && okexp(nl)) { + if (submac(nl, lvl+1)) { + /* Could expand, result on lexbuffer */ + stringbuf = och; /* clear saved name */ + anychange = 1; + } + } else if (bidx) { + /* must restore blocks */ + stringbuf = och; + for (i = 0; i < bidx; i++) + savch(EBLOCK), savch(bptr[i] & 255), + savch(bptr[i] >> 8); + savstr(yytext); + } + bidx = 0; + IMP("EA2"); + break; + + case CMNT: + getcmnt(); + break; + + case '\n': + cinput(); + savch(' '); + break; + + default: + savstr((usch *)yytext); + break; + } + } + *stringbuf = 0; + cunput(WARN); + unpstr(osb); + DPRINT(("%d:exparg return: change %d\n", lvl, anychange)); + IMP("EXPRET"); + stringbuf = osb; + if (anychange) + goto rescan; + readmac--; +} + +void +imp(const char *str) +{ + printf("%s (%d) '", str, bidx); + prline(ifiles->curptr); + printf("'\n"); +} + +void +prrep(const usch *s) +{ + while (*s) { + switch (*s) { + case WARN: printf("", *--s); break; + case CONC: printf(""); break; + case SNUFF: printf(""); break; + case EBLOCK: printf("",s[-1] + s[-2] * 256); s-=2; break; + default: printf("%c", *s); break; + } + s--; + } +} + +void +prline(const usch *s) +{ + while (*s) { + switch (*s) { + case WARN: printf(""); break; + case CONC: printf(""); break; + case SNUFF: printf(""); break; + case EBLOCK: printf("",s[1] + s[2] * 256); s+=2; break; + case '\n': printf(""); break; + default: printf("%c", *s); break; + } + s++; + } +} + +usch * +savstr(const usch *str) +{ + usch *rv = stringbuf; + + do { + if (stringbuf >= &sbf[SBSIZE]) { + stringbuf = sbf; /* need space to write error message */ + error("out of macro space!"); + } + } while ((*stringbuf++ = *str++)); + stringbuf--; + return rv; +} + +void +unpstr(const usch *c) +{ + const usch *d = c; + +#if 0 + if (dflag>1) { + printf("Xunpstr: '"); + prline(c); + printf("'\n"); + } +#endif + while (*d) { + if (*d == EBLOCK) + d += 2; + d++; + } + while (d > c) { + cunput(*--d); + } +} + +void +flbuf() +{ + if (obufp == 0) + return; + if (Mflag == 0 && write(ofd, outbuf, obufp) < 0) + error("obuf write error"); + lastoch = outbuf[obufp-1]; + obufp = 0; +} + +void +putch(int ch) +{ + outbuf[obufp++] = (usch)ch; + if (obufp == CPPBUF || (istty && ch == '\n')) + flbuf(); +} + +void +putstr(const usch *s) +{ + for (; *s; s++) { + outbuf[obufp++] = *s; + if (obufp == CPPBUF || (istty && *s == '\n')) + flbuf(); + } +} + +/* + * convert a number to an ascii string. Store it on the heap. + */ +static void +num2str(int num) +{ + static usch buf[12]; + usch *b = buf; + int m = 0; + + if (num < 0) + num = -num, m = 1; + do { + *b++ = (usch)(num % 10 + '0'); + num /= 10; + } while (num); + if (m) + *b++ = '-'; + while (b > buf) + savch(*--b); +} + +/* + * similar to sprintf, but only handles %s and %d. + * saves result on heap. + */ +usch * +sheap(const char *fmt, ...) +{ + va_list ap; + usch *op = stringbuf; + + va_start(ap, fmt); + for (; *fmt; fmt++) { + if (*fmt == '%') { + fmt++; + switch (*fmt) { + case 's': + savstr(va_arg(ap, usch *)); + break; + case 'd': + num2str(va_arg(ap, int)); + break; + case 'c': + savch(va_arg(ap, int)); + break; + default: + break; /* cannot call error() here */ + } + } else + savch(*fmt); + } + va_end(ap); + *stringbuf = 0; + return op; +} + +void +usage() +{ + error("Usage: cpp [-Cdt] [-Dvar=val] [-Uvar] [-Ipath] [-Spath]"); +} + +#ifdef notyet +/* + * Symbol table stuff. + * The data structure used is a patricia tree implementation using only + * bytes to store offsets. + * The information stored is (lower address to higher): + * + * unsigned char bitno[2]; bit number in the string + * unsigned char left[3]; offset from base to left element + * unsigned char right[3]; offset from base to right element + */ +#endif + +/* + * This patricia implementation is more-or-less the same as + * used in ccom for string matching. + */ +struct tree { + int bitno; + struct tree *lr[2]; +}; + +#define BITNO(x) ((x) & ~(LEFT_IS_LEAF|RIGHT_IS_LEAF)) +#define LEFT_IS_LEAF 0x80000000 +#define RIGHT_IS_LEAF 0x40000000 +#define IS_LEFT_LEAF(x) (((x) & LEFT_IS_LEAF) != 0) +#define IS_RIGHT_LEAF(x) (((x) & RIGHT_IS_LEAF) != 0) +#define P_BIT(key, bit) (key[bit >> 3] >> (bit & 7)) & 1 +#define CHECKBITS 8 + +static struct tree *sympole; +static int numsyms; + +/* + * Allocate a symtab struct and store the string. + */ +static struct symtab * +getsymtab(const usch *str) +{ + struct symtab *sp = malloc(sizeof(struct symtab)); + + if (sp == NULL) + error("getsymtab: couldn't allocate symtab"); + sp->namep = savstr(str); + savch('\0'); + sp->value = NULL; + sp->file = ifiles ? ifiles->orgfn : (const usch *)""; + sp->line = ifiles ? ifiles->lineno : 0; + return sp; +} + +/* + * Do symbol lookup in a patricia tree. + * Only do full string matching, no pointer optimisations. + */ +struct symtab * +lookup(const usch *key, int enterf) +{ + struct symtab *sp; + struct tree *w, *new, *last; + int len, cix, bit, fbit, svbit, ix, bitno; + const usch *k, *m, *sm; + + /* Count full string length */ + for (k = key, len = 0; *k; k++, len++) + ; + + switch (numsyms) { + case 0: /* no symbols yet */ + if (enterf != ENTER) + return NULL; + sympole = (struct tree *)getsymtab(key); + numsyms++; + return (struct symtab *)sympole; + + case 1: + w = sympole; + svbit = 0; /* XXX gcc */ + break; + + default: + w = sympole; + bitno = len * CHECKBITS; + for (;;) { + bit = BITNO(w->bitno); + fbit = bit > bitno ? 0 : P_BIT(key, bit); + svbit = fbit ? IS_RIGHT_LEAF(w->bitno) : + IS_LEFT_LEAF(w->bitno); + w = w->lr[fbit]; + if (svbit) + break; + } + } + + sp = (struct symtab *)w; + + sm = m = sp->namep; + k = key; + + /* Check for correct string and return */ + for (cix = 0; *m && *k && *m == *k; m++, k++, cix += CHECKBITS) + ; + if (*m == 0 && *k == 0) { + if (enterf != ENTER && sp->value == NULL) + return NULL; + return sp; + } + + if (enterf != ENTER) + return NULL; /* no string found and do not enter */ + + ix = *m ^ *k; + while ((ix & 1) == 0) + ix >>= 1, cix++; + + /* Create new node */ + if ((new = malloc(sizeof *new)) == NULL) + error("getree: couldn't allocate tree"); + bit = P_BIT(key, cix); + new->bitno = cix | (bit ? RIGHT_IS_LEAF : LEFT_IS_LEAF); + new->lr[bit] = (struct tree *)getsymtab(key); + + if (numsyms++ == 1) { + new->lr[!bit] = sympole; + new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF); + sympole = new; + return (struct symtab *)new->lr[bit]; + } + + w = sympole; + last = NULL; + for (;;) { + fbit = w->bitno; + bitno = BITNO(w->bitno); + if (bitno == cix) + error("bitno == cix"); + if (bitno > cix) + break; + svbit = P_BIT(key, bitno); + last = w; + w = w->lr[svbit]; + if (fbit & (svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF)) + break; + } + + new->lr[!bit] = w; + if (last == NULL) { + sympole = new; + } else { + last->lr[svbit] = new; + last->bitno &= ~(svbit ? RIGHT_IS_LEAF : LEFT_IS_LEAF); + } + if (bitno < cix) + new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF); + return (struct symtab *)new->lr[bit]; +} + +usch * +xstrdup(const usch *str) +{ + size_t len = strlen((const char *)str)+1; + usch *rv; + + if ((rv = malloc(len)) == NULL) + error("xstrdup: out of mem"); + strlcpy((char *)rv, (const char *)str, len); + return rv; +} diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/cpp.h b/compilers/pcc/pcc-1.0.0/cc/cpp/cpp.h new file mode 100644 index 00000000..ab0d42d7 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/cpp.h @@ -0,0 +1,184 @@ +/* $Id: cpp.h,v 1.47.2.1 2011/02/26 06:36:40 ragge Exp $ */ + +/* + * Copyright (c) 2004,2010 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include /* for obuf */ +#include + +#include "config.h" + +typedef unsigned char usch; +extern usch yytext[]; +extern usch *stringbuf; + +extern int trulvl; +extern int flslvl; +extern int elflvl; +extern int elslvl; +extern int tflag, Cflag, Pflag; +extern int Mflag, dMflag; +extern usch *Mfile; +extern int ofd; + +/* args for lookup() */ +#define FIND 0 +#define ENTER 1 + +/* buffer used internally */ +#ifndef CPPBUF +#if defined(__pdp11__) +#define CPPBUF BUFSIZ +#define BUF_STACK +#elif defined(WIN32) +/* winxp seems to fail > 26608 bytes */ +#define CPPBUF 16384 +#else +#define CPPBUF (65536*2) +#endif +#endif + +#define MAXARGS 128 /* Max # of args to a macro. Should be enouth */ + +#define NAMEMAX CPPBUF /* currently pushbackbuffer */ +#define BBUFSZ (NAMEMAX+CPPBUF+1) + +#define GCCARG 0xfd /* has gcc varargs that may be replaced with 0 */ +#define VARG 0xfe /* has varargs */ +#define OBJCT 0xff +#define WARN 1 /* SOH, not legal char */ +#define CONC 2 /* STX, not legal char */ +#define SNUFF 3 /* ETX, not legal char */ +#define EBLOCK 4 /* EOT, not legal char */ + +/* Used in macro expansion */ +#define RECMAX 10000 /* max # of recursive macros */ +extern struct symtab *norep[RECMAX]; +extern int norepptr; +extern unsigned short bptr[RECMAX]; +extern int bidx; +#define MKB(l,h) (l+((h)<<8)) + +/* quick checks for some characters */ +#define C_SPEC 001 +#define C_EP 002 +#define C_ID 004 +#define C_I (C_SPEC|C_ID) +#define C_2 010 /* for yylex() tokenizing */ +#define C_WSNL 020 /* ' ','\t','\r','\n' */ +#define iswsnl(x) (spechr[x] & C_WSNL) +extern char spechr[]; + +/* definition for include file info */ +struct includ { + struct includ *next; + const usch *fname; /* current fn, changed if #line found */ + const usch *orgfn; /* current fn, not changed */ + int lineno; + int infil; + usch *curptr; + usch *maxread; + usch *ostr; + usch *buffer; + int idx; + void *incs; + const usch *fn; +#ifdef BUF_STACK + usch bbuf[BBUFSZ]; +#else + usch *bbuf; +#endif +} *ifiles; + +/* Symbol table entry */ +struct symtab { + const usch *namep; + const usch *value; + const usch *file; + int line; +}; + +struct initar { + struct initar *next; + int type; + char *str; +}; + +/* + * Struct used in parse tree evaluation. + * op is one of: + * - number type (NUMBER, UNUMBER) + * - zero (0) if divided by zero. + */ +struct nd { + int op; + union { + long long val; + unsigned long long uval; + } n; +}; + +#define nd_val n.val +#define nd_uval n.uval + +struct symtab *lookup(const usch *namep, int enterf); +usch *gotident(struct symtab *nl); +int slow; /* scan slowly for new tokens */ +int submac(struct symtab *nl, int); +int kfind(struct symtab *nl); +int doexp(void); +int donex(void); + +int pushfile(const usch *fname, const usch *fn, int idx, void *incs); +void popfile(void); +void prtline(void); +int yylex(void); +int sloscan(void); +void cunput(int); +int curline(void); +char *curfile(void); +void setline(int); +void setfile(char *); +int yyparse(void); +void yyerror(const char *); +void unpstr(const usch *); +usch *savstr(const usch *str); +void savch(int c); +void mainscan(void); +void putch(int); +void putstr(const usch *s); +void line(void); +usch *sheap(const char *fmt, ...); +void xwarning(usch *); +void xerror(usch *); +#ifdef HAVE_CPP_VARARG_MACRO_GCC +#define warning(...) xwarning(sheap(__VA_ARGS__)) +#define error(...) xerror(sheap(__VA_ARGS__)) +#else +#define warning printf +#define error printf +#endif +int cinput(void); +void getcmnt(void); diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/cpy.y b/compilers/pcc/pcc-1.0.0/cc/cpp/cpy.y new file mode 100644 index 00000000..8f8924e5 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/cpy.y @@ -0,0 +1,221 @@ +/* $Id: cpy.y,v 1.18 2010/02/25 15:49:00 ragge Exp $ */ + +/* + * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code and documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +%{ + +#include "cpp.h" + +void yyerror(const char *); +int yylex(void); +int setd(int l, int r); + +#define EVALUNARY(tok, l, r) l.nd_val = tok r.nd_val; l.op = r.op +#define EVALBIN(tok, d, l, r) \ + d.op = setd(l.op, r.op); d.nd_val = l.nd_val tok r.nd_val +#define EVALUBIN(tok, d, l, r, t) \ + d.op = setd(l.op, r.op); \ + if (d.op == NUMBER) d.nd_val = l.nd_val tok r.nd_val; \ + else d.nd_uval = l.nd_uval tok r.nd_uval; \ + if (t && d.op) d.op = NUMBER +#define XEVALUBIN(tok, d, l, r) \ + if (r.nd_val) { EVALUBIN(tok, d, l, r, 0); } else d.op = 0 +%} + +%term stop +%term EQ NE LE GE LS RS +%term ANDAND OROR IDENT NUMBER UNUMBER DEFINED +/* + * The following terminals are not used in the yacc code. + */ +%term STRING WSPACE CMNT + +%left ',' +%right '?' ':' +%left OROR +%left ANDAND +%left '|' '^' +%left '&' +%binary EQ NE +%binary '<' '>' LE GE +%left LS RS +%left '+' '-' +%left '*' '/' '%' +%right '!' '~' UMINUS +%left '(' + +%union { + struct nd node; +} + +%type term e NUMBER UNUMBER + +%% +S: e '\n' { + if ($1.op == 0) + error("division by zero"); + return $1.nd_val; + } + +e: e '*' e + { EVALUBIN(*, $$, $1, $3, 0); } + | e '/' e + { XEVALUBIN(/, $$, $1, $3); } + | e '%' e + { XEVALUBIN(%, $$, $1, $3); } + | e '+' e + { EVALBIN(+, $$, $1, $3); } + | e '-' e + { EVALBIN(-, $$, $1, $3); } + | e LS e + { EVALBIN(<<, $$, $1, $3); } + | e RS e + { EVALUBIN(>>, $$, $1, $3, 0); } + | e '<' e + { EVALUBIN(<, $$, $1, $3, 1); } + | e '>' e + { EVALUBIN(>, $$, $1, $3, 1); } + | e LE e + { EVALUBIN(<=, $$, $1, $3, 1); } + | e GE e + { EVALUBIN(>=, $$, $1, $3, 1); } + | e EQ e + { EVALUBIN(==, $$, $1, $3, 1); } + | e NE e + { EVALUBIN(!=, $$, $1, $3, 1); } + | e '&' e + { EVALBIN(&, $$, $1, $3); } + | e '^' e + { EVALBIN(^, $$, $1, $3); } + | e '|' e + { EVALBIN(|, $$, $1, $3); } + | e ANDAND e { + $$ = $1; + if ($1.nd_val) { + $$.op = setd($1.op, $3.op); + $$.nd_val = ($3.nd_val != 0); + } + if ($$.op == UNUMBER) $$.op = NUMBER; + } + | e OROR e { + if ($1.nd_val != 0) { + $$.nd_val = ($1.nd_val != 0); + $$.op = $1.op; + } else { + $$.nd_val = ($3.nd_val != 0); + $$.op = setd($1.op, $3.op); + } + if ($$.op == UNUMBER) $$.op = NUMBER; + } + | e '?' e ':' e { + if ($1.op == 0) + $$ = $1; + else if ($1.nd_val) + $$ = $3; + else + $$ = $5; + } + | e ',' e { + $$.op = setd($1.op, $3.op); + $$.nd_val = $3.nd_val; + if ($$.op) $$.op = $3.op; + } + | term + {$$ = $1;} +term: + '-' term %prec UMINUS + { EVALUNARY(-, $$, $2); } + | '+' term %prec UMINUS + {$$ = $2;} + | '!' term + { $$.nd_val = ! $2.nd_val; $$.op = $2.op ? NUMBER : 0; } + | '~' term + { EVALUNARY(~, $$, $2); } + | '(' e ')' + {$$ = $2;} + | DEFINED '(' NUMBER ')' + {$$= $3;} + | DEFINED NUMBER + {$$ = $2;} + | NUMBER + {$$ = $1;} +%% + +void +yyerror(const char *err) +{ + error(err); +} + +/* + * Set return type of an expression. + */ +int +setd(int l, int r) +{ + if (!l || !r) + return 0; /* div by zero involved */ + if (l == UNUMBER || r == UNUMBER) + return UNUMBER; + return NUMBER; +} + diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/scanner.l b/compilers/pcc/pcc-1.0.0/cc/cpp/scanner.l new file mode 100644 index 00000000..f1e4bf97 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/scanner.l @@ -0,0 +1,939 @@ +%{ +/* $Id: scanner.l,v 1.49 2009/02/14 09:23:55 ragge Exp $ */ + +/* + * Copyright (c) 2004 Anders Magnusson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include + +#include "compat.h" +#include "cpp.h" +#include "y.tab.h" +%} + +%{ +static void cvtdig(int rad); +static int charcon(usch *); +static void elsestmt(void); +static void ifdefstmt(void); +static void ifndefstmt(void); +static void endifstmt(void); +static void ifstmt(void); +static void cpperror(void); +static void pragmastmt(void); +static void undefstmt(void); +static void cpperror(void); +static void elifstmt(void); +static void storepb(void); +static void badop(const char *); +void include(void); +void define(void); + +extern int yyget_lineno (void); +extern void yyset_lineno (int); + +static int inch(void); + +static int scale, gotdef, contr; +int inif; + +#ifdef FLEX_SCANNER /* should be set by autoconf instead */ +static int +yyinput(char *b, int m) +{ + int c, i; + + for (i = 0; i < m; i++) { + if ((c = inch()) < 0) + break; + *b++ = c; + if (c == '\n') { + i++; + break; + } + } + return i; +} +#undef YY_INPUT +#undef YY_BUF_SIZE +#define YY_BUF_SIZE (8*65536) +#define YY_INPUT(b,r,m) (r = yyinput(b, m)) +#ifdef HAVE_CPP_VARARG_MACRO_GCC +#define fprintf(x, ...) error(__VA_ARGS__) +#endif +#define ECHO putstr((usch *)yytext) +#undef fileno +#define fileno(x) 0 + +#if YY_FLEX_SUBMINOR_VERSION >= 31 +/* Hack to avoid unnecessary warnings */ +FILE *yyget_in (void); +FILE *yyget_out (void); +int yyget_leng (void); +char *yyget_text (void); +void yyset_in (FILE * in_str ); +void yyset_out (FILE * out_str ); +int yyget_debug (void); +void yyset_debug (int bdebug ); +int yylex_destroy (void); +#endif +#else /* Assume lex here */ +#undef input +#undef unput +#define input() inch() +#define unput(ch) unch(ch) +#endif +#define PRTOUT(x) if (YYSTATE || slow) return x; if (!flslvl) putstr((usch *)yytext); +/* protection against recursion in #include */ +#define MAX_INCLEVEL 100 +static int inclevel; +%} + +D [0-9] +L [a-zA-Z_] +H [a-fA-F0-9] +E [Ee][+-]?{D}+ +FS (f|F|l|L) +IS (u|U|l|L)* +WS [\t ] + +%s IFR CONTR DEF COMMENT + +%% + +"\n" { int os = YYSTATE; + if (os != IFR) + BEGIN 0; + ifiles->lineno++; + if (flslvl == 0) { + if (ifiles->lineno == 1) + prtline(); + else + putch('\n'); + } + if ((os != 0 || slow) && !contr) + return '\n'; + contr = 0; + } + +"\r" { ; /* Ignore CR's */ } + +"++" { badop("++"); } +"--" { badop("--"); } +"==" { return EQ; } +"!=" { return NE; } +"<=" { return LE; } +"<<" { return LS; } +">>" { return RS; } +">=" { return GE; } +"||" { return OROR; } +"&&" { return ANDAND; } +"defined" { int p, c; + gotdef = 1; + if ((p = c = yylex()) == '(') + c = yylex(); + if (c != IDENT || (p != IDENT && p != '(')) + error("syntax error"); + if (p == '(' && yylex() != ')') + error("syntax error"); + return NUMBER; + } + +{WS}+ { ; } +{L}({L}|{D})* { + yylval.node.op = NUMBER; + if (gotdef) { + yylval.node.nd_val + = lookup((usch *)yytext, FIND) != 0; + gotdef = 0; + return IDENT; + } + yylval.node.nd_val = 0; + return NUMBER; + } + +[0-9][0-9]* { + if (slow && !YYSTATE) + return IDENT; + scale = yytext[0] == '0' ? 8 : 10; + goto num; + } + +0[xX]{H}+{IS}? { scale = 16; + num: if (YYSTATE == IFR) + cvtdig(scale); + PRTOUT(NUMBER); + } +0{D}+{IS}? { scale = 8; goto num; } +{D}+{IS}? { scale = 10; goto num; } +'(\\.|[^\\'])+' { + if (YYSTATE || slow) { + yylval.node.op = NUMBER; + yylval.node.nd_val = charcon((usch *)yytext); + return (NUMBER); + } + if (tflag) + yyless(1); + if (!flslvl) + putstr((usch *)yytext); + } + +. { return yytext[0]; } + +{D}+{E}{FS}? { PRTOUT(FPOINT); } +{D}*"."{D}+({E})?{FS}? { PRTOUT(FPOINT); } +{D}+"."{D}*({E})?{FS}? { PRTOUT(FPOINT); } + +^{WS}*#{WS}* { extern int inmac; + + if (inmac) + error("preprocessor directive found " + "while expanding macro"); + contr = 1; + BEGIN CONTR; + } +{WS}+ { PRTOUT(WSPACE); } + +"ifndef" { contr = 0; ifndefstmt(); } +"ifdef" { contr = 0; ifdefstmt(); } +"if" { contr = 0; storepb(); BEGIN IFR; ifstmt(); BEGIN 0; } +"include" { contr = 0; BEGIN 0; include(); prtline(); } +"else" { contr = 0; elsestmt(); } +"endif" { contr = 0; endifstmt(); } +"error" { contr = 0; if (slow) return IDENT; cpperror(); BEGIN 0; } +"define" { contr = 0; BEGIN DEF; define(); BEGIN 0; } +"undef" { contr = 0; if (slow) return IDENT; undefstmt(); } +"line" { contr = 0; storepb(); BEGIN 0; line(); } +"pragma" { contr = 0; pragmastmt(); BEGIN 0; } +"elif" { contr = 0; storepb(); BEGIN IFR; elifstmt(); BEGIN 0; } + + + +"//".*$ { /* if (tflag) yyless(..) */ + if (Cflag && !flslvl && !slow) + putstr((usch *)yytext); + else if (!flslvl) + putch(' '); + } +"/*" { int c, wrn; + int prtcm = Cflag && !flslvl && !slow; + extern int readmac; + + if (Cflag && !flslvl && readmac) + return CMNT; + + if (prtcm) + putstr((usch *)yytext); + wrn = 0; + more: while ((c = input()) && c != '*') { + if (c == '\n') + putch(c), ifiles->lineno++; + else if (c == 1) /* WARN */ + wrn = 1; + else if (prtcm) + putch(c); + } + if (c == 0) + return 0; + if (prtcm) + putch(c); + if ((c = input()) && c != '/') { + unput(c); + goto more; + } + if (prtcm) + putch(c); + if (c == 0) + return 0; + if (!tflag && !Cflag && !flslvl) + unput(' '); + if (wrn) + unput(1); + } + +"##" { return CONCAT; } +"#" { return MKSTR; } +"..." { return ELLIPS; } +"__VA_ARGS__" { return VA_ARGS; } + +L?\"(\\.|[^\\"])*\" { PRTOUT(STRING); } +[a-zA-Z_0-9]+ { /* {L}({L}|{D})* */ + struct symtab *nl; + if (slow) + return IDENT; + if (YYSTATE == CONTR) { + if (flslvl == 0) { + /*error("undefined control");*/ + while (input() != '\n') + ; + unput('\n'); + BEGIN 0; + goto xx; + } else { + BEGIN 0; /* do nothing */ + } + } + if (flslvl) { + ; /* do nothing */ + } else if (isdigit((int)yytext[0]) == 0 && + (nl = lookup((usch *)yytext, FIND)) != 0) { + usch *op = stringbuf; + putstr(gotident(nl)); + stringbuf = op; + } else + putstr((usch *)yytext); + xx: ; + } + +. { + if (contr) { + while (input() != '\n') + ; + unput('\n'); + BEGIN 0; + contr = 0; + goto yy; + } + if (YYSTATE || slow) + return yytext[0]; + if (yytext[0] == 6) { /* PRAGS */ + usch *obp = stringbuf; + extern usch *prtprag(usch *); + *stringbuf++ = yytext[0]; + do { + *stringbuf = input(); + } while (*stringbuf++ != 14); + prtprag(obp); + stringbuf = obp; + } else { + PRTOUT(yytext[0]); + } + yy:; + } + +%% + +usch *yyp, yybuf[CPPBUF]; + +int yylex(void); +int yywrap(void); + +static int +inpch(void) +{ + int len; + + if (ifiles->curptr < ifiles->maxread) + return *ifiles->curptr++; + + if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0) + error("read error on file %s", ifiles->orgfn); + if (len == 0) + return -1; + ifiles->curptr = ifiles->buffer; + ifiles->maxread = ifiles->buffer + len; + return inpch(); +} + +#define unch(c) *--ifiles->curptr = c + +static int +inch(void) +{ + int c; + +again: switch (c = inpch()) { + case '\\': /* continued lines */ +msdos: if ((c = inpch()) == '\n') { + ifiles->lineno++; + putch('\n'); + goto again; + } else if (c == '\r') + goto msdos; + unch(c); + return '\\'; + case '?': /* trigraphs */ + if ((c = inpch()) != '?') { + unch(c); + return '?'; + } + switch (c = inpch()) { + case '=': c = '#'; break; + case '(': c = '['; break; + case ')': c = ']'; break; + case '<': c = '{'; break; + case '>': c = '}'; break; + case '/': c = '\\'; break; + case '\'': c = '^'; break; + case '!': c = '|'; break; + case '-': c = '~'; break; + default: + unch(c); + unch('?'); + return '?'; + } + unch(c); + goto again; + default: + return c; + } +} + +/* + * Let the command-line args be faked defines at beginning of file. + */ +static void +prinit(struct initar *it, struct includ *ic) +{ + char *a, *pre, *post; + + if (it->next) + prinit(it->next, ic); + pre = post = NULL; /* XXX gcc */ + switch (it->type) { + case 'D': + pre = "#define "; + if ((a = strchr(it->str, '=')) != NULL) { + *a = ' '; + post = "\n"; + } else + post = " 1\n"; + break; + case 'U': + pre = "#undef "; + post = "\n"; + break; + case 'i': + pre = "#include \""; + post = "\"\n"; + break; + default: + error("prinit"); + } + strlcat((char *)ic->buffer, pre, CPPBUF+1); + strlcat((char *)ic->buffer, it->str, CPPBUF+1); + if (strlcat((char *)ic->buffer, post, CPPBUF+1) >= CPPBUF+1) + error("line exceeds buffer size"); + + ic->lineno--; + while (*ic->maxread) + ic->maxread++; +} + +/* + * A new file included. + * If ifiles == NULL, this is the first file and already opened (stdin). + * Return 0 on success, -1 if file to be included is not found. + */ +int +pushfile(usch *file) +{ + extern struct initar *initar; + struct includ ibuf; + struct includ *ic; + int c, otrulvl; + + ic = &ibuf; + ic->next = ifiles; + + slow = 0; + if (file != NULL) { + if ((ic->infil = open((char *)file, O_RDONLY)) < 0) + return -1; + ic->orgfn = ic->fname = file; + if (++inclevel > MAX_INCLEVEL) + error("Limit for nested includes exceeded"); + } else { + ic->infil = 0; + ic->orgfn = ic->fname = (usch *)""; + } + ic->buffer = ic->bbuf+NAMEMAX; + ic->curptr = ic->buffer; + ifiles = ic; + ic->lineno = 1; + ic->maxread = ic->curptr; + prtline(); + if (initar) { + *ic->maxread = 0; + prinit(initar, ic); + if (dMflag) + write(ofd, ic->buffer, strlen((char *)ic->buffer)); + initar = NULL; + } + + otrulvl = trulvl; + + if ((c = yylex()) != 0) + error("yylex returned %d", c); + + if (otrulvl != trulvl || flslvl) + error("unterminated conditional"); + + ifiles = ic->next; + close(ic->infil); + inclevel--; + return 0; +} + +/* + * Print current position to output file. + */ +void +prtline() +{ + usch *s, *os = stringbuf; + + if (Mflag) { + if (dMflag) + return; /* no output */ + if (ifiles->lineno == 1) { + s = sheap("%s: %s\n", Mfile, ifiles->fname); + write(ofd, s, strlen((char *)s)); + } + } else if (!Pflag) + putstr(sheap("# %d \"%s\"\n", ifiles->lineno, ifiles->fname)); + stringbuf = os; +} + +void +cunput(int c) +{ +#ifdef CPP_DEBUG + extern int dflag; + if (dflag)printf(": '%c'(%d)", c > 31 ? c : ' ', c); +#endif + unput(c); +} + +int yywrap(void) { return 1; } + +static int +dig2num(int c) +{ + if (c >= 'a') + c = c - 'a' + 10; + else if (c >= 'A') + c = c - 'A' + 10; + else + c = c - '0'; + return c; +} + +/* + * Convert string numbers to unsigned long long and check overflow. + */ +static void +cvtdig(int rad) +{ + unsigned long long rv = 0; + unsigned long long rv2 = 0; + char *y = yytext; + int c; + + c = *y++; + if (rad == 16) + y++; + while (isxdigit(c)) { + rv = rv * rad + dig2num(c); + /* check overflow */ + if (rv / rad < rv2) + error("Constant \"%s\" is out of range", yytext); + rv2 = rv; + c = *y++; + } + y--; + while (*y == 'l' || *y == 'L') + y++; + yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER; + yylval.node.nd_uval = rv; + if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0) + yylval.node.op = UNUMBER; + if (yylval.node.op == NUMBER && yylval.node.nd_val < 0) + /* too large for signed */ + error("Constant \"%s\" is out of range", yytext); +} + +static int +charcon(usch *p) +{ + int val, c; + + p++; /* skip first ' */ + val = 0; + if (*p++ == '\\') { + switch (*p++) { + case 'a': val = '\a'; break; + case 'b': val = '\b'; break; + case 'f': val = '\f'; break; + case 'n': val = '\n'; break; + case 'r': val = '\r'; break; + case 't': val = '\t'; break; + case 'v': val = '\v'; break; + case '\"': val = '\"'; break; + case '\'': val = '\''; break; + case '\\': val = '\\'; break; + case 'x': + while (isxdigit(c = *p)) { + val = val * 16 + dig2num(c); + p++; + } + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': + p--; + while (isdigit(c = *p)) { + val = val * 8 + (c - '0'); + p++; + } + break; + default: val = p[-1]; + } + + } else + val = p[-1]; + return val; +} + +static void +chknl(int ignore) +{ + int t; + + slow = 1; + while ((t = yylex()) == WSPACE) + ; + if (t != '\n') { + if (ignore) { + warning("newline expected, got \"%s\"", yytext); + /* ignore rest of line */ + while ((t = yylex()) && t != '\n') + ; + } + else + error("newline expected, got \"%s\"", yytext); + } + slow = 0; +} + +static void +elsestmt(void) +{ + if (flslvl) { + if (elflvl > trulvl) + ; + else if (--flslvl!=0) { + flslvl++; + } else { + trulvl++; + prtline(); + } + } else if (trulvl) { + flslvl++; + trulvl--; + } else + error("If-less else"); + if (elslvl==trulvl+flslvl) + error("Too many else"); + elslvl=trulvl+flslvl; + chknl(1); +} + +static void +ifdefstmt(void) +{ + int t; + + if (flslvl) { + /* just ignore the rest of the line */ + while (input() != '\n') + ; + unput('\n'); + yylex(); + flslvl++; + return; + } + slow = 1; + do + t = yylex(); + while (t == WSPACE); + if (t != IDENT) + error("bad ifdef"); + slow = 0; + if (flslvl == 0 && lookup((usch *)yytext, FIND) != 0) + trulvl++; + else + flslvl++; + chknl(0); +} + +static void +ifndefstmt(void) +{ + int t; + + slow = 1; + do + t = yylex(); + while (t == WSPACE); + if (t != IDENT) + error("bad ifndef"); + slow = 0; + if (flslvl == 0 && lookup((usch *)yytext, FIND) == 0) + trulvl++; + else + flslvl++; + chknl(0); +} + +static void +endifstmt(void) +{ + if (flslvl) { + flslvl--; + if (flslvl == 0) + prtline(); + } else if (trulvl) + trulvl--; + else + error("If-less endif"); + if (flslvl == 0) + elflvl = 0; + elslvl = 0; + chknl(1); +} + +/* + * Note! Ugly! + * Walk over the string s and search for defined, and replace it with + * spaces and a 1 or 0. + */ +static void +fixdefined(usch *s) +{ + usch *bc, oc; + + for (; *s; s++) { + if (*s != 'd') + continue; + if (memcmp(s, "defined", 7)) + continue; + /* Ok, got defined, can scratch it now */ + memset(s, ' ', 7); + s += 7; +#define WSARG(x) (x == ' ' || x == '\t') + if (*s != '(' && !WSARG(*s)) + continue; + while (WSARG(*s)) + s++; + if (*s == '(') + s++; + while (WSARG(*s)) + s++; +#define IDARG(x) ((x>= 'A' && x <= 'Z') || (x >= 'a' && x <= 'z') || (x == '_')) +#define NUMARG(x) (x >= '0' && x <= '9') + if (!IDARG(*s)) + error("bad defined arg"); + bc = s; + while (IDARG(*s) || NUMARG(*s)) + s++; + oc = *s; + *s = 0; + *bc = (lookup(bc, FIND) != 0) + '0'; + memset(bc+1, ' ', s-bc-1); + *s = oc; + } +} + +/* + * get the full line of identifiers after an #if, pushback a WARN and + * the line and prepare for expmac() to expand. + * This is done before switching state. When expmac is finished, + * pushback the expanded line, change state and call yyparse. + */ +static void +storepb(void) +{ + usch *opb = stringbuf; + int c; + + while ((c = input()) != '\n') { + if (c == '/') { + if ((c = input()) == '*') { + /* ignore comments here whatsoever */ + usch *g = stringbuf; + getcmnt(); + stringbuf = g; + continue; + } else if (c == '/') { + while ((c = input()) && c != '\n') + ; + break; + } + unput(c); + c = '/'; + } + savch(c); + } + cunput('\n'); + savch(0); + fixdefined(opb); /* XXX can fail if #line? */ + cunput(1); /* WARN XXX */ + unpstr(opb); + stringbuf = opb; + slow = 1; + expmac(NULL); + slow = 0; + /* line now expanded */ + while (stringbuf > opb) + cunput(*--stringbuf); +} + +static void +ifstmt(void) +{ + if (flslvl == 0) { + slow = 1; + if (yyparse()) + ++trulvl; + else + ++flslvl; + slow = 0; + } else + ++flslvl; +} + +static void +elifstmt(void) +{ + if (flslvl == 0) + elflvl = trulvl; + if (flslvl) { + if (elflvl > trulvl) + ; + else if (--flslvl!=0) + ++flslvl; + else { + slow = 1; + if (yyparse()) { + ++trulvl; + prtline(); + } else + ++flslvl; + slow = 0; + } + } else if (trulvl) { + ++flslvl; + --trulvl; + } else + error("If-less elif"); +} + +static usch * +svinp(void) +{ + int c; + usch *cp = stringbuf; + + while ((c = input()) && c != '\n') + savch(c); + savch('\n'); + savch(0); + BEGIN 0; + return cp; +} + +static void +cpperror(void) +{ + usch *cp; + int c; + + if (flslvl) + return; + c = yylex(); + if (c != WSPACE && c != '\n') + error("bad error"); + cp = svinp(); + if (flslvl) + stringbuf = cp; + else + error("%s", cp); +} + +static void +undefstmt(void) +{ + struct symtab *np; + + slow = 1; + if (yylex() != WSPACE || yylex() != IDENT) + error("bad undef"); + if (flslvl == 0 && (np = lookup((usch *)yytext, FIND))) + np->value = 0; + slow = 0; + chknl(0); +} + +static void +pragmastmt(void) +{ + int c; + + slow = 1; + if (yylex() != WSPACE) + error("bad pragma"); + if (!flslvl) + putstr((usch *)"#pragma "); + do { + c = input(); + if (!flslvl) + putch(c); /* Do arg expansion instead? */ + } while (c && c != '\n'); + ifiles->lineno++; + prtline(); + slow = 0; +} + +static void +badop(const char *op) +{ + error("invalid operator in preprocessor expression: %s", op); +} + +int +cinput() +{ + return input(); +} diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/CVS/Entries b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/CVS/Entries new file mode 100644 index 00000000..d2238b30 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/CVS/Entries @@ -0,0 +1,27 @@ +/res1/1.3/Fri Nov 5 15:54:49 2010//Tr-1-0-0-RELEASE +/res10/1.1/Sat Dec 18 15:22:13 2010//Tr-1-0-0-RELEASE +/res11/1.1/Sun Jan 9 15:21:33 2011//Tr-1-0-0-RELEASE +/res12/1.1/Sun Jan 9 15:21:33 2011//Tr-1-0-0-RELEASE +/res13/1.1/Sun Jan 16 11:59:09 2011//Tr-1-0-0-RELEASE +/res2/1.4/Sun Jan 9 15:21:33 2011//Tr-1-0-0-RELEASE +/res3/1.4/Fri Nov 5 15:54:49 2010//Tr-1-0-0-RELEASE +/res4/1.2/Fri Nov 5 15:54:49 2010//Tr-1-0-0-RELEASE +/res5/1.2/Fri Nov 5 15:54:49 2010//Tr-1-0-0-RELEASE +/res6/1.2/Fri Nov 5 15:54:49 2010//Tr-1-0-0-RELEASE +/res7/1.3/Fri Nov 5 15:54:49 2010//Tr-1-0-0-RELEASE +/res8/1.2/Fri Nov 5 15:54:49 2010//Tr-1-0-0-RELEASE +/res9/1.2/Fri Nov 5 15:54:49 2010//Tr-1-0-0-RELEASE +/test1/1.1/Sun Jul 30 12:12:07 2006//Tr-1-0-0-RELEASE +/test10/1.1/Sat Dec 18 15:22:13 2010//Tr-1-0-0-RELEASE +/test11/1.1/Sun Jan 9 15:21:34 2011//Tr-1-0-0-RELEASE +/test12/1.1/Sun Jan 9 15:21:34 2011//Tr-1-0-0-RELEASE +/test13/1.1/Sun Jan 16 11:59:09 2011//Tr-1-0-0-RELEASE +/test2/1.1/Sun Jul 30 12:12:07 2006//Tr-1-0-0-RELEASE +/test3/1.1/Sun Jul 30 12:12:07 2006//Tr-1-0-0-RELEASE +/test4/1.1/Sun Jul 30 12:12:07 2006//Tr-1-0-0-RELEASE +/test5/1.1/Sun Jul 30 12:12:07 2006//Tr-1-0-0-RELEASE +/test6/1.1/Sat Oct 7 09:13:04 2006//Tr-1-0-0-RELEASE +/test7/1.1/Sat Oct 7 09:13:04 2006//Tr-1-0-0-RELEASE +/test8/1.1/Sat Oct 7 09:13:04 2006//Tr-1-0-0-RELEASE +/test9/1.1/Tue Jan 2 19:49:02 2007//Tr-1-0-0-RELEASE +D diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/CVS/Repository b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/CVS/Repository new file mode 100644 index 00000000..4cfdbd29 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/CVS/Repository @@ -0,0 +1 @@ +pcc/cc/cpp/tests diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/CVS/Root b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/CVS/Root new file mode 100644 index 00000000..71e2ccb9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/CVS/Root @@ -0,0 +1 @@ +/cvsroot diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/CVS/Tag b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/CVS/Tag new file mode 100644 index 00000000..060fac05 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/CVS/Tag @@ -0,0 +1 @@ +Nr-1-0-0-RELEASE diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res1 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res1 new file mode 100644 index 00000000..bff9a250 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res1 @@ -0,0 +1,8 @@ + +# 1 "" + + + + +char p[] = "x ## y"; + diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res10 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res10 new file mode 100644 index 00000000..5f294c9b --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res10 @@ -0,0 +1,16 @@ + +# 1 "" + + + + + +int midiopen(int); + + + + + + + +foo_optarg diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res11 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res11 new file mode 100644 index 00000000..4c49d185 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res11 @@ -0,0 +1,22 @@ + +# 1 "" + + + + + +a +a b +a b c +a b c d + + + + + + +__attribute__((__noreturn__)) + + +1 2 + diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res12 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res12 new file mode 100644 index 00000000..1420d399 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res12 @@ -0,0 +1,21 @@ + +# 1 "" + + + + + +2 2 2 2 2; + + + + + + + + + + + + +(0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res13 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res13 new file mode 100644 index 00000000..5ec9b411 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res13 @@ -0,0 +1,13 @@ + +# 1 "" + + + + +long + + + + + + diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res2 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res2 new file mode 100644 index 00000000..e9fb624e --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res2 @@ -0,0 +1,27 @@ + +# 1 "" + + + + + + + + + + + + + + +f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1); +f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & +f(2 * (0,1))^m(0,1); +int i[] = { 1, 23, 4, 5, }; +char c[2][6] = { "hello", "" }; + + + + + + diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res3 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res3 new file mode 100644 index 00000000..9f19a1f9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res3 @@ -0,0 +1,16 @@ + +# 1 "" + + + + + + + + +printf("x" "1" "= %d, x" "2" "= %s", x1, x2); +fputs( +"strncmp(\"abc\\0d\", \"abc\", '\\4') == 0" ": @\n", s); +\#include "vers2.h" +"hello"; +"hello" ", world" diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res4 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res4 new file mode 100644 index 00000000..8e7649ab --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res4 @@ -0,0 +1,6 @@ + +# 1 "" + + + +(1) diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res5 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res5 new file mode 100644 index 00000000..7d57f95a --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res5 @@ -0,0 +1,5 @@ + +# 1 "" + +int j[] = { 123, 45, 67, 89, + 10, 11, 12, }; diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res6 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res6 new file mode 100644 index 00000000..a739c9ba --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res6 @@ -0,0 +1,5 @@ + +# 1 "" + + +foo diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res7 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res7 new file mode 100644 index 00000000..6d7c47c1 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res7 @@ -0,0 +1,6 @@ + +# 1 "" + + +a +YES diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res8 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res8 new file mode 100644 index 00000000..118ead4d --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res8 @@ -0,0 +1,9 @@ + +# 1 "" + + + + + +(hej.s_s.s_pos) + diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res9 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res9 new file mode 100644 index 00000000..631ecf16 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/res9 @@ -0,0 +1,6 @@ + +# 1 "" + + + +ao diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test1 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test1 new file mode 100644 index 00000000..79a3c5dc --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test1 @@ -0,0 +1,6 @@ +#define hash_hash # ## # +#define mkstr(a) # a +#define in_between(a) mkstr(a) +#define join(c, d) in_between(c hash_hash d) +char p[] = join(x, y); // equivalent to + // char p[] = "x ## y"; diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test10 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test10 new file mode 100644 index 00000000..dfba8b37 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test10 @@ -0,0 +1,14 @@ +#define __CONCAT(x,y) x ## y +#define dev_type_open(n) int n(int) +#define dev_decl(n,t) __CONCAT(dev_type_,t)(__CONCAT(n,t)) +#define cdev_decl(n) dev_decl(n,open) + +cdev_decl(midi); + +# define __GETOPT_PREFIX foo_ +# define __GETOPT_CONCAT(x, y) x ## y +# define __GETOPT_XCONCAT(x, y) __GETOPT_CONCAT (x, y) +# define __GETOPT_ID(y) __GETOPT_XCONCAT (__GETOPT_PREFIX, y) +# define optarg __GETOPT_ID (optarg) + +optarg diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test11 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test11 new file mode 100644 index 00000000..5bf4249f --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test11 @@ -0,0 +1,20 @@ +#define D1(s, ...) s +#define D2(s, ...) s D1(__VA_ARGS__) +#define D3(s, ...) s D2(__VA_ARGS__) +#define D4(s, ...) s D3(__VA_ARGS__) + +D1(a) +D2(a, b) +D3(a, b, c) +D4(a, b, c, d) + + +#define __sun_attr___noreturn__ __attribute__((__noreturn__)) +#define ___sun_attr_inner(__a) __sun_attr_##__a +#define __sun_attr__(__a) ___sun_attr_inner __a +#define __NORETURN __sun_attr__((__noreturn__)) +__NORETURN +#define X(...) +#define Y(...) 1 __VA_ARGS__ 2 +Y(X X() ()) + diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test12 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test12 new file mode 100644 index 00000000..a0a36f12 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test12 @@ -0,0 +1,19 @@ +#define y 2 +#define fe(p) sfe(p) p +#define sfe(p) p +#define Y fe(y) y fe(y) + +Y; + +# define S2B_QMIN 0 +# define S2B_CMIN (S2B_QMIN + 8) +#define S2B_1(i) i, +#define S2B_2(i) S2B_1(i) S2B_1(i) +#define S2B_4(i) S2B_2(i) S2B_2(i) +#define S2B_8(i) S2B_4(i) S2B_4(i) +#define S2B_16(i) S2B_8(i) S2B_8(i) +#define S2B_32(i) S2B_16(i) S2B_16(i) +#define S2B_64(i) S2B_32(i) S2B_32(i) +#define S2B_128(i) S2B_64(i) S2B_64(i) +#define S2B_256(i) S2B_128(i) S2B_128(i) +S2B_256(S2B_CMIN + 0) diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test13 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test13 new file mode 100644 index 00000000..51e2385d --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test13 @@ -0,0 +1,11 @@ + +#define UL long, foo +#define D(I,F) I +#define E(I) D(I) +E(UL) + +#define FOO 1 + +#if (FOO == 1) + +#endif /* FOO */ diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test2 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test2 new file mode 100644 index 00000000..283d4fbc --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test2 @@ -0,0 +1,25 @@ +#define x 3 +#define f(a) f(x * (a)) +#undef x +#define x 2 +#define g f +#define z z[0] +#define h g(~ +#define m(a) a(w) +#define w 0,1 +#define t(a) a +#define p() int +#define q(x) x +#define r(x,y) x ## y +#define str(x) # x +f(y+1) + f(f(z)) % t(t(g)(0) + t)(1); +g(x+(3,4)-w) | h 5) & m +(f)^m(m); +p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) }; +char c[2][6] = { str(hello), str() }; +/* + * f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1); + * f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1); + * int i[] = { 1, 23, 4, 5, }; + * char c[2][6] = { "hello", "" }; + */ diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test3 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test3 new file mode 100644 index 00000000..a659245e --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test3 @@ -0,0 +1,15 @@ +#define str(s) # s +#define xstr(s) str(s) +#define debug(s, t) printf("x" # s "= %d, x" # t "= %s", \ + x ## s, x ## t) +#define INCFILE(n) vers ## n +#define glue(a, b) a ## b +#define xglue(a, b) glue(a, b) +#define HIGHLOW "hello" +#define LOW LOW ", world" +debug(1, 2); +fputs(str(strncmp("abc\0d", "abc", '\4') // this goes away + == 0) str(: @\n), s); +\#include xstr(INCFILE(2).h) +glue(HIGH, LOW); +xglue(HIGH, LOW) diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test4 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test4 new file mode 100644 index 00000000..0068f375 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test4 @@ -0,0 +1,4 @@ +#define foobar 1 +#define C(x,y) x##y +#define D(x) (C(x,bar)) +D(foo) diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test5 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test5 new file mode 100644 index 00000000..3ca0bb6c --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test5 @@ -0,0 +1,3 @@ +#define t(x,y,z) x ## y ## z +int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), + t(10,,), t(,11,), t(,,12), t(,,) }; diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test6 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test6 new file mode 100644 index 00000000..28cfddec --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test6 @@ -0,0 +1,5 @@ +#define X(a,b, \ + c,d) \ + foo + +X(1,2,3,4) diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test7 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test7 new file mode 100644 index 00000000..b22b22bb --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test7 @@ -0,0 +1,4 @@ +#define a() YES +#define b() a +b() +b()() diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test8 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test8 new file mode 100644 index 00000000..c5d2f9a1 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test8 @@ -0,0 +1,7 @@ +// test macro expansion in arguments +#define s_pos s_s.s_pos +#define foo(x) (x) + +//hej.s_pos +foo(hej.s_pos) + diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test9 b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test9 new file mode 100644 index 00000000..4d4368d5 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/tests/test9 @@ -0,0 +1,4 @@ +#define C(a,b,c) a##b##c +#define N(x,y) C(x,_,y) +#define A_O ao +N(A,O) diff --git a/compilers/pcc/pcc-1.0.0/cc/cpp/token.c b/compilers/pcc/pcc-1.0.0/cc/cpp/token.c new file mode 100644 index 00000000..9f086ee8 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/cc/cpp/token.c @@ -0,0 +1,1318 @@ +/* $Id: token.c,v 1.48.2.2 2011/03/12 17:08:26 ragge Exp $ */ + +/* + * Copyright (c) 2004,2009 Anders Magnusson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Tokenizer for the C preprocessor. + * There are three main routines: + * - fastscan() loops over the input stream searching for magic + * characters that may require actions. + * - sloscan() tokenize the input stream and returns tokens. + * It may recurse into itself during expansion. + * - yylex() returns something from the input stream that + * is suitable for yacc. + * + * Other functions of common use: + * - inpch() returns a raw character from the current input stream. + * - inch() is like inpch but \\n and trigraphs are expanded. + * - unch() pushes back a character to the input stream. + */ + +#include "config.h" + +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include + +#include "compat.h" +#include "cpp.h" +#include "y.tab.h" + +static void cvtdig(int rad); +static int charcon(usch *); +static void elsestmt(void); +static void ifdefstmt(void); +static void ifndefstmt(void); +static void endifstmt(void); +static void ifstmt(void); +static void cpperror(void); +static void pragmastmt(void); +static void undefstmt(void); +static void cppwarning(void); +static void elifstmt(void); +static void badop(const char *); +static int chktg(void); +static void ppdir(void); +void include(void); +void include_next(void); +void define(void); +static int inpch(void); + +extern int yyget_lineno (void); +extern void yyset_lineno (int); + +static int inch(void); + +int inif; +extern int dflag; + +#define PUTCH(ch) if (!flslvl) putch(ch) +/* protection against recursion in #include */ +#define MAX_INCLEVEL 100 +static int inclevel; + +/* get next character unaltered */ +#define NXTCH() (ifiles->curptr < ifiles->maxread ? *ifiles->curptr++ : inpch()) + +usch yytext[CPPBUF]; + +char spechr[256] = { + 0, 0, 0, 0, C_SPEC, C_SPEC, 0, 0, + 0, C_WSNL, C_SPEC|C_WSNL, 0, + 0, C_WSNL, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + C_WSNL, C_2, C_SPEC, 0, 0, 0, C_2, C_SPEC, + 0, 0, 0, C_2, 0, C_2, 0, C_SPEC|C_2, + C_I, C_I, C_I, C_I, C_I, C_I, C_I, C_I, + C_I, C_I, 0, 0, C_2, C_2, C_2, C_SPEC, + + 0, C_I, C_I, C_I, C_I, C_I|C_EP, C_I, C_I, + C_I, C_I, C_I, C_I, C_I, C_I, C_I, C_I, + C_I|C_EP, C_I, C_I, C_I, C_I, C_I, C_I, C_I, + C_I, C_I, C_I, 0, C_I, 0, 0, C_I, + + 0, C_I, C_I, C_I, C_I, C_I|C_EP, C_I, C_I, + C_I, C_I, C_I, C_I, C_I, C_I, C_I, C_I, + C_I|C_EP, C_I, C_I, C_I, C_I, C_I, C_I, C_I, + C_I, C_I, C_I, 0, C_2, 0, 0, 0, + +}; + +/* + * No-replacement array. If a macro is found and exists in this array + * then no replacement shall occur. This is a stack. + */ +struct symtab *norep[RECMAX]; /* Symbol table index table */ +int norepptr = 1; /* Top of index table */ +unsigned short bptr[RECMAX]; /* currently active noexpand macro stack */ +int bidx; /* Top of bptr stack */ + +static void +unch(int c) +{ + + --ifiles->curptr; + if (ifiles->curptr < ifiles->bbuf) + error("pushback buffer full"); + *ifiles->curptr = (usch)c; +} + +static int +eatcmnt(void) +{ + int ch; + + if (Cflag) { PUTCH('/'); PUTCH('*'); } + for (;;) { + ch = inch(); + if (ch == '\n') { + ifiles->lineno++; + PUTCH('\n'); + } + if (ch == -1) + return -1; + if (ch == '*') { + ch = inch(); + if (ch == '/') { + if (Cflag) { + PUTCH('*'); + PUTCH('/'); + } else + PUTCH(' '); + break; + } + unch(ch); + ch = '*'; + } + if (Cflag) PUTCH(ch); + } + return 0; +} + +/* + * Scan quickly the input file searching for: + * - '#' directives + * - keywords (if not flslvl) + * - comments + * + * Handle strings, numbers and trigraphs with care. + * Only data from pp files are scanned here, never any rescans. + * TODO: Only print out strings before calling other functions. + */ +static void +fastscan(void) +{ + struct symtab *nl; + int ch, i, ccnt, onemore; + usch *cp; + + goto run; + for (;;) { + ch = NXTCH(); +xloop: if (ch == -1) + return; + if (dflag>1) + printf("fastscan ch %d (%c)\n", ch, ch > 31 ? ch : '@'); + if ((spechr[ch] & C_SPEC) == 0) { + PUTCH(ch); + continue; + } + switch (ch) { + case EBLOCK: + case WARN: + case CONC: + error("bad char passed"); + break; + + case '/': /* Comments */ + if ((ch = inch()) == '/') { +cppcmt: if (Cflag) { PUTCH(ch); } else { PUTCH(' '); } + do { + if (Cflag) PUTCH(ch); + ch = inch(); + } while (ch != -1 && ch != '\n'); + goto xloop; + } else if (ch == '*') { + if (eatcmnt()) + return; + } else { + PUTCH('/'); + goto xloop; + } + break; + + case '?': /* trigraphs */ + if ((ch = chktg())) + goto xloop; + PUTCH('?'); + break; + + case '\\': + if ((ch = NXTCH()) == '\n') { + ifiles->lineno++; + continue; + } else { + PUTCH('\\'); + } + goto xloop; + + case '\n': /* newlines, for pp directives */ +run2: ifiles->lineno++; + do { + PUTCH(ch); +run: ch = NXTCH(); + if (ch == '/') { + ch = NXTCH(); + if (ch == '/') + goto cppcmt; + if (ch == '*') { + if (eatcmnt()) + return; + goto run; + } + unch(ch); + ch = '/'; + } + } while (ch == ' ' || ch == '\t'); + if (ch == '\\') { + ch = NXTCH(); + if (ch == '\n') + goto run2; + unch(ch); + ch = '\\'; + } + if (ch == '#') { + ppdir(); + continue; + } else if (ch == '%') { + ch = NXTCH(); + if (ch == ':') { + ppdir(); + continue; + } else { + unch(ch); + ch = '%'; + } + } + goto xloop; + + case '\"': /* strings */ +str: PUTCH(ch); + while ((ch = inch()) != '\"') { + PUTCH(ch); + if (ch == '\\') { + ch = inch(); + PUTCH(ch); + } + if (ch < 0) + return; + } + PUTCH(ch); + break; + + case '.': /* for pp-number */ + PUTCH(ch); + ch = NXTCH(); + if (ch < '0' || ch > '9') + goto xloop; + /* FALLTHROUGH */ + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + do { + PUTCH(ch); +nxt: ch = NXTCH(); + if (ch == '\\') { + ch = NXTCH(); + if (ch == '\n') { + goto nxt; + } else { + unch(ch); + ch = '\\'; + } + } + if (spechr[ch] & C_EP) { + PUTCH(ch); + ch = NXTCH(); + if (ch == '-' || ch == '+') + continue; + } + } while ((spechr[ch] & C_ID) || (ch == '.')); + goto xloop; + + case '\'': /* character literal */ +con: PUTCH(ch); + if (tflag) + continue; /* character constants ignored */ + while ((ch = NXTCH()) != '\'') { + PUTCH(ch); + if (ch == '\\') { + ch = NXTCH(); + PUTCH(ch); + } else if (ch < 0) + return; + else if (ch == '\n') + goto xloop; + } + PUTCH(ch); + break; + + case 'L': + ch = NXTCH(); + if (ch == '\"') { + PUTCH('L'); + goto str; + } + if (ch == '\'') { + PUTCH('L'); + goto con; + } + unch(ch); + ch = 'L'; + /* FALLTHROUGH */ + default: + if ((spechr[ch] & C_ID) == 0) + error("fastscan"); + if (flslvl) { + while (spechr[ch] & C_ID) + ch = NXTCH(); + goto xloop; + } + onemore = i = ccnt = 0; + do { + yytext[i++] = (usch)ch; + ch = NXTCH(); + if (ch == '\\') { + ch = NXTCH(); + if (ch != '\n') { + unch('\n'); + ch = '\\'; + } else { + ifiles->lineno++; + ch = NXTCH(); + } + } + if (ch < 0) + return; + } while (spechr[ch] & C_ID); + + yytext[i] = 0; + unch(ch); + + cp = stringbuf; + if ((nl = lookup((usch *)yytext, FIND)) && kfind(nl)) { + putstr(stringbuf); + } else + putstr((usch *)yytext); + stringbuf = cp; + + break; + } + } +} + +int +sloscan() +{ + int ch; + int yyp; + +zagain: + yyp = 0; + ch = inch(); + yytext[yyp++] = (usch)ch; + switch (ch) { + case -1: + return 0; + case '\n': + /* sloscan() never passes \n, that's up to fastscan() */ + unch(ch); + goto yyret; + + case '\r': /* Ignore CR's */ + yyp = 0; + break; + + case '0': case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + /* readin a "pp-number" */ +ppnum: for (;;) { + ch = inch(); + if (spechr[ch] & C_EP) { + yytext[yyp++] = (usch)ch; + ch = inch(); + if (ch == '-' || ch == '+') { + yytext[yyp++] = (usch)ch; + } else + unch(ch); + continue; + } + if ((spechr[ch] & C_ID) || ch == '.') { + yytext[yyp++] = (usch)ch; + continue; + } + break; + } + unch(ch); + yytext[yyp] = 0; + + return NUMBER; + + case '\'': +chlit: + for (;;) { + if ((ch = inch()) == '\\') { + yytext[yyp++] = (usch)ch; + yytext[yyp++] = (usch)inch(); + continue; + } else if (ch == '\n') { + /* not a constant */ + while (yyp > 1) + unch(yytext[--yyp]); + ch = '\''; + goto any; + } else + yytext[yyp++] = (usch)ch; + if (ch == '\'') + break; + } + yytext[yyp] = 0; + + return (NUMBER); + + case ' ': + case '\t': + while ((ch = inch()) == ' ' || ch == '\t') + yytext[yyp++] = (usch)ch; + unch(ch); + yytext[yyp] = 0; + return(WSPACE); + + case '/': + if ((ch = inch()) == '/') { + do { + yytext[yyp++] = (usch)ch; + ch = inch(); + } while (ch && ch != '\n'); + yytext[yyp] = 0; + unch(ch); + goto zagain; + } else if (ch == '*') { + int c, wrn; + extern int readmac; + + if (Cflag && !flslvl && readmac) { + unch(ch); + yytext[yyp] = 0; + return CMNT; + } + + wrn = 0; + more: while ((c = inch()) && c != '*') { + if (c == '\n') + putch(c), ifiles->lineno++; + else if (c == EBLOCK) { + (void)inch(); + (void)inch(); + } else if (c == 1) /* WARN */ + wrn = 1; + } + if (c == 0) + return 0; + if ((c = inch()) && c != '/') { + unch(c); + goto more; + } + if (c == 0) + return 0; + if (!tflag && !Cflag && !flslvl) + unch(' '); + if (wrn) + unch(1); + goto zagain; + } + unch(ch); + ch = '/'; + goto any; + + case '.': + ch = inch(); + if (isdigit(ch)) { + yytext[yyp++] = (usch)ch; + goto ppnum; + } else { + unch(ch); + ch = '.'; + } + goto any; + + case '\"': + if (tflag) + goto any; + strng: + for (;;) { + if ((ch = inch()) == '\\') { + yytext[yyp++] = (usch)ch; + yytext[yyp++] = (usch)inch(); + continue; + } else + yytext[yyp++] = (usch)ch; + if (ch == '\"') + break; + } + yytext[yyp] = 0; + return(STRING); + + case 'L': + if ((ch = inch()) == '\"' && !tflag) { + yytext[yyp++] = (usch)ch; + goto strng; + } else if (ch == '\'' && !tflag) { + yytext[yyp++] = (usch)ch; + goto chlit; + } + unch(ch); + /* FALLTHROUGH */ + + /* Yetch, all identifiers */ + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': + case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': + case 's': case 't': case 'u': case 'v': case 'w': case 'x': + case 'y': case 'z': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'G': case 'H': case 'I': case 'J': case 'K': + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': + case 'Y': case 'Z': + case '_': /* {L}({L}|{D})* */ + + /* Special hacks */ + for (;;) { /* get chars */ + ch = inch(); + if (isalpha(ch) || isdigit(ch) || ch == '_') { + yytext[yyp++] = (usch)ch; + } else { + unch(ch); + break; + } + } + yytext[yyp] = 0; /* need already string */ + /* end special hacks */ + + return IDENT; + default: + any: + yytext[yyp] = 0; + return yytext[0]; + + } /* endcase */ + goto zagain; + +yyret: + yytext[yyp] = 0; + return ch; +} + +int +yylex() +{ + static int ifdef, noex; + struct symtab *nl; + int ch, c2; + + while ((ch = sloscan()) == WSPACE) + ; + if (ch < 128 && spechr[ch] & C_2) + c2 = inpch(); + else + c2 = 0; + +#define C2(a,b,c) case a: if (c2 == b) return c; break + switch (ch) { + C2('=', '=', EQ); + C2('!', '=', NE); + C2('|', '|', OROR); + C2('&', '&', ANDAND); + case '<': + if (c2 == '<') return LS; + if (c2 == '=') return LE; + break; + case '>': + if (c2 == '>') return RS; + if (c2 == '=') return GE; + break; + case '+': + case '-': + if (ch == c2) + badop(""); + break; + + case '/': + if (Cflag == 0 || c2 != '*') + break; + /* Found comment that need to be skipped */ + for (;;) { + ch = inpch(); + c1: if (ch != '*') + continue; + if ((ch = inpch()) == '/') + break; + goto c1; + } + return yylex(); + + case NUMBER: + if (yytext[0] == '\'') { + yylval.node.op = NUMBER; + yylval.node.nd_val = charcon((usch *)yytext); + } else + cvtdig(yytext[0] != '0' ? 10 : + yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8); + return NUMBER; + + case IDENT: + if (strcmp((char *)yytext, "defined") == 0) { + ifdef = 1; + return DEFINED; + } + nl = lookup((usch *)yytext, FIND); + if (ifdef) { + yylval.node.nd_val = nl != NULL; + ifdef = 0; + } else if (nl && noex == 0) { + usch *och = stringbuf; + int i; + + i = kfind(nl); + unch(WARN); + if (i) + unpstr(stringbuf); + else + unpstr(nl->namep); + stringbuf = och; + noex = 1; + return yylex(); + } else { + yylval.node.nd_val = 0; + } + yylval.node.op = NUMBER; + return NUMBER; + case WARN: + noex = 0; + return yylex(); + default: + return ch; + } + unch(c2); + return ch; +} + +usch *yyp, yybuf[CPPBUF]; + +int yywrap(void); + +static int +inpch(void) +{ + int len; + + if (ifiles->curptr < ifiles->maxread) + return *ifiles->curptr++; + + if (ifiles->infil == -1) + return -1; + if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0) + error("read error on file %s", ifiles->orgfn); + if (len == 0) + return -1; + ifiles->curptr = ifiles->buffer; + ifiles->maxread = ifiles->buffer + len; + return inpch(); +} + +static int +inch(void) +{ + int c; + +again: switch (c = inpch()) { + case '\\': /* continued lines */ +msdos: if ((c = inpch()) == '\n') { + ifiles->lineno++; + goto again; + } else if (c == '\r') + goto msdos; + unch(c); + return '\\'; + case '?': /* trigraphs */ + if ((c = chktg())) { + unch(c); + goto again; + } + return '?'; + default: + return c; + } +} + +/* + * Let the command-line args be faked defines at beginning of file. + */ +static void +prinit(struct initar *it, struct includ *ic) +{ + const char *pre, *post; + char *a; + + if (it->next) + prinit(it->next, ic); + pre = post = NULL; /* XXX gcc */ + switch (it->type) { + case 'D': + pre = "#define "; + if ((a = strchr(it->str, '=')) != NULL) { + *a = ' '; + post = "\n"; + } else + post = " 1\n"; + break; + case 'U': + pre = "#undef "; + post = "\n"; + break; + case 'i': + pre = "#include \""; + post = "\"\n"; + break; + default: + error("prinit"); + } + strlcat((char *)ic->buffer, pre, CPPBUF+1); + strlcat((char *)ic->buffer, it->str, CPPBUF+1); + if (strlcat((char *)ic->buffer, post, CPPBUF+1) >= CPPBUF+1) + error("line exceeds buffer size"); + + ic->lineno--; + while (*ic->maxread) + ic->maxread++; +} + +/* + * A new file included. + * If ifiles == NULL, this is the first file and already opened (stdin). + * Return 0 on success, -1 if file to be included is not found. + */ +int +pushfile(const usch *file, const usch *fn, int idx, void *incs) +{ + extern struct initar *initar; + struct includ ibuf; + struct includ *ic; + int otrulvl; + + ic = &ibuf; + ic->next = ifiles; + + if (file != NULL) { + if ((ic->infil = open((const char *)file, O_RDONLY)) < 0) + return -1; + ic->orgfn = ic->fname = file; + if (++inclevel > MAX_INCLEVEL) + error("Limit for nested includes exceeded"); + } else { + ic->infil = 0; + ic->orgfn = ic->fname = (const usch *)""; + } +#ifndef BUF_STACK + ic->bbuf = malloc(BBUFSZ); +#endif + ic->buffer = ic->bbuf+NAMEMAX; + ic->curptr = ic->buffer; + ifiles = ic; + ic->lineno = 1; + ic->maxread = ic->curptr; + ic->idx = idx; + ic->incs = incs; + ic->fn = fn; + prtline(); + if (initar) { + int oin = ic->infil; + ic->infil = -1; + *ic->maxread = 0; + prinit(initar, ic); + initar = NULL; + if (dMflag) + write(ofd, ic->buffer, strlen((char *)ic->buffer)); + fastscan(); + prtline(); + ic->infil = oin; + } + + otrulvl = trulvl; + + fastscan(); + + if (otrulvl != trulvl || flslvl) + error("unterminated conditional"); + +#ifndef BUF_STACK + free(ic->bbuf); +#endif + ifiles = ic->next; + close(ic->infil); + inclevel--; + return 0; +} + +/* + * Print current position to output file. + */ +void +prtline() +{ + usch *s, *os = stringbuf; + + if (Mflag) { + if (dMflag) + return; /* no output */ + if (ifiles->lineno == 1) { + s = sheap("%s: %s\n", Mfile, ifiles->fname); + write(ofd, s, strlen((char *)s)); + } + } else if (!Pflag) + putstr(sheap("\n# %d \"%s\"\n", ifiles->lineno, ifiles->fname)); + stringbuf = os; +} + +void +cunput(int c) +{ +#ifdef CPP_DEBUG +// extern int dflag; +// if (dflag)printf(": '%c'(%d)\n", c > 31 ? c : ' ', c); +#endif +#if 0 +if (c == 10) { + printf("c == 10!!!\n"); +} +#endif + unch(c); +} + +int yywrap(void) { return 1; } + +static int +dig2num(int c) +{ + if (c >= 'a') + c = c - 'a' + 10; + else if (c >= 'A') + c = c - 'A' + 10; + else + c = c - '0'; + return c; +} + +/* + * Convert string numbers to unsigned long long and check overflow. + */ +static void +cvtdig(int rad) +{ + unsigned long long rv = 0; + unsigned long long rv2 = 0; + usch *y = yytext; + int c; + + c = *y++; + if (rad == 16) + y++; + while (isxdigit(c)) { + rv = rv * rad + dig2num(c); + /* check overflow */ + if (rv / rad < rv2) + error("Constant \"%s\" is out of range", yytext); + rv2 = rv; + c = *y++; + } + y--; + while (*y == 'l' || *y == 'L') + y++; + yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER; + yylval.node.nd_uval = rv; + if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0) + yylval.node.op = UNUMBER; + if (yylval.node.op == NUMBER && yylval.node.nd_val < 0) + /* too large for signed, see 6.4.4.1 */ + error("Constant \"%s\" is out of range", yytext); +} + +static int +charcon(usch *p) +{ + int val, c; + + p++; /* skip first ' */ + val = 0; + if (*p++ == '\\') { + switch (*p++) { + case 'a': val = '\a'; break; + case 'b': val = '\b'; break; + case 'f': val = '\f'; break; + case 'n': val = '\n'; break; + case 'r': val = '\r'; break; + case 't': val = '\t'; break; + case 'v': val = '\v'; break; + case '\"': val = '\"'; break; + case '\'': val = '\''; break; + case '\\': val = '\\'; break; + case 'x': + while (isxdigit(c = *p)) { + val = val * 16 + dig2num(c); + p++; + } + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': + p--; + while (isdigit(c = *p)) { + val = val * 8 + (c - '0'); + p++; + } + break; + default: val = p[-1]; + } + + } else + val = p[-1]; + return val; +} + +static void +chknl(int ignore) +{ + int t; + + while ((t = sloscan()) == WSPACE) + ; + if (t != '\n') { + if (ignore) { + warning("newline expected, got \"%s\"", yytext); + /* ignore rest of line */ + while ((t = sloscan()) && t != '\n') + ; + } + else + error("newline expected, got \"%s\"", yytext); + } +} + +static void +elsestmt(void) +{ + if (flslvl) { + if (elflvl > trulvl) + ; + else if (--flslvl!=0) { + flslvl++; + } else { + trulvl++; + prtline(); + } + } else if (trulvl) { + flslvl++; + trulvl--; + } else + error("If-less else"); + if (elslvl==trulvl+flslvl) + error("Too many else"); + elslvl=trulvl+flslvl; + chknl(1); +} + +static void +skpln(void) +{ + /* just ignore the rest of the line */ + while (inch() != '\n') + ; + unch('\n'); + flslvl++; +} + +static void +ifdefstmt(void) +{ + int t; + + if (flslvl) { + skpln(); + return; + } + do + t = sloscan(); + while (t == WSPACE); + if (t != IDENT) + error("bad ifdef"); + if (lookup((usch *)yytext, FIND) == 0) { + putch('\n'); + flslvl++; + } else + trulvl++; + chknl(0); +} + +static void +ifndefstmt(void) +{ + int t; + + if (flslvl) { + skpln(); + return; + } + do + t = sloscan(); + while (t == WSPACE); + if (t != IDENT) + error("bad ifndef"); + if (lookup((usch *)yytext, FIND) != 0) { + putch('\n'); + flslvl++; + } else + trulvl++; + chknl(0); +} + +static void +endifstmt(void) +{ + if (flslvl) { + flslvl--; + if (flslvl == 0) { + putch('\n'); + prtline(); + } + } else if (trulvl) + trulvl--; + else + error("If-less endif"); + if (flslvl == 0) + elflvl = 0; + elslvl = 0; + chknl(1); +} + +static void +ifstmt(void) +{ + if (flslvl == 0) { + if (yyparse() == 0) { + putch('\n'); + ++flslvl; + } else + ++trulvl; + } else + ++flslvl; +} + +static void +elifstmt(void) +{ + if (flslvl == 0) + elflvl = trulvl; + if (flslvl) { + if (elflvl > trulvl) + ; + else if (--flslvl!=0) + ++flslvl; + else { + if (yyparse()) { + ++trulvl; + prtline(); + } else { + putch('\n'); + ++flslvl; + } + } + } else if (trulvl) { + ++flslvl; + --trulvl; + } else + error("If-less elif"); +} + +static usch * +svinp(void) +{ + int c; + usch *cp = stringbuf; + + while ((c = inch()) && c != '\n') + savch(c); + savch('\n'); + savch(0); + return cp; +} + +static void +cpperror(void) +{ + usch *cp; + int c; + + if (flslvl) + return; + c = sloscan(); + if (c != WSPACE && c != '\n') + error("bad error"); + cp = svinp(); + if (flslvl) + stringbuf = cp; + else + error("%s", cp); +} + +static void +cppwarning(void) +{ + usch *cp; + int c; + + if (flslvl) + return; + c = sloscan(); + if (c != WSPACE && c != '\n') + error("bad warning"); + + /* svinp() add an unwanted \n */ + cp = stringbuf; + while ((c = inch()) && c != '\n') + savch(c); + savch(0); + + if (flslvl) + stringbuf = cp; + else + warning("#warning %s", cp); + + unch('\n'); +} + +static void +undefstmt(void) +{ + struct symtab *np; + + if (sloscan() != WSPACE || sloscan() != IDENT) + error("bad undef"); + if (flslvl == 0 && (np = lookup((usch *)yytext, FIND))) + np->value = 0; + chknl(0); +} + +static void +pragmastmt(void) +{ + int c; + + if (sloscan() != WSPACE) + error("bad pragma"); + if (!flslvl) + putstr((const usch *)"\n#pragma "); + do { + c = inch(); + if (!flslvl) + putch(c); /* Do arg expansion instead? */ + } while (c && c != '\n'); + if (c == '\n') + unch(c); + prtline(); +} + +static void +badop(const char *op) +{ + error("invalid operator in preprocessor expression: %s", op); +} + +int +cinput() +{ + return inch(); +} + +/* + * Check for (and convert) trigraphs. + */ +int +chktg() +{ + int c; + + if ((c = inpch()) != '?') { + unch(c); + return 0; + } + switch (c = inpch()) { + case '=': c = '#'; break; + case '(': c = '['; break; + case ')': c = ']'; break; + case '<': c = '{'; break; + case '>': c = '}'; break; + case '/': c = '\\'; break; + case '\'': c = '^'; break; + case '!': c = '|'; break; + case '-': c = '~'; break; + default: + unch(c); + unch('?'); + c = 0; + } + return c; +} + +static struct { + const char *name; + void (*fun)(void); +} ppd[] = { + { "ifndef", ifndefstmt }, + { "ifdef", ifdefstmt }, + { "if", ifstmt }, + { "include", include }, + { "else", elsestmt }, + { "endif", endifstmt }, + { "error", cpperror }, + { "warning", cppwarning }, + { "define", define }, + { "undef", undefstmt }, + { "line", line }, + { "pragma", pragmastmt }, + { "elif", elifstmt }, +#ifdef GCC_COMPAT + { "include_next", include_next }, +#endif +}; + +/* + * Handle a preprocessor directive. + */ +void +ppdir(void) +{ + char bp[20]; + int ch, i; + + while ((ch = inch()) == ' ' || ch == '\t') + ; + if (ch == '\n') { /* empty directive */ + unch(ch); + return; + } + if (ch < 'a' || ch > 'z') + goto out; /* something else, ignore */ + i = 0; + do { + bp[i++] = (usch)ch; + if (i == sizeof(bp)-1) + goto out; /* too long */ + ch = inch(); + } while ((ch >= 'a' && ch <= 'z') || (ch == '_')); + unch(ch); + bp[i++] = 0; + + /* got keyword */ +#define SZ (int)(sizeof(ppd)/sizeof(ppd[0])) + for (i = 0; i < SZ; i++) + if (bp[0] == ppd[i].name[0] && strcmp(bp, ppd[i].name) == 0) + break; + if (i == SZ) + goto out; + + /* Found matching keyword */ + (*ppd[i].fun)(); + return; + +out: while ((ch = inch()) != '\n' && ch != -1) + ; + unch('\n'); +} diff --git a/compilers/pcc/pcc-1.0.0/config.guess b/compilers/pcc/pcc-1.0.0/config.guess new file mode 100644 index 00000000..278f9e9e --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/config.guess @@ -0,0 +1,1516 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, +# Inc. + +timestamp='2007-07-22' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:[3456]*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + EM64T | authenticamd) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa:Linux:*:*) + echo xtensa-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^LIBC/{ + s: ::g + p + }'`" + test x"${LIBC}" != x && { + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit + } + test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/compilers/pcc/pcc-1.0.0/config.h.in b/compilers/pcc/pcc-1.0.0/config.h.in new file mode 100644 index 00000000..85d178c6 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/config.h.in @@ -0,0 +1,176 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Using a.out ABI */ +#undef AOUTABI + +/* Define path to alternate assembler */ +#undef ASSEMBLER + +/* Using Classic 68k ABI */ +#undef CLASSIC68K + +/* Using COFF ABI */ +#undef COFFABI + +/* Define path to alternate compiler */ +#undef COMPILER + +/* Using ECOFF ABI */ +#undef ECOFFABI + +/* Using ELF ABI */ +#undef ELFABI + +/* Define to 1 if you have the `basename' function. */ +#undef HAVE_BASENAME + +/* Define to 1 if printf supports C99 size specifiers */ +#undef HAVE_C99_FORMAT + +/* Define to 1 if your compiler supports C99 variadic macros */ +#undef HAVE_CPP_VARARG_MACRO_GCC + +/* Define to 1 if you have the `ffs' function. */ +#undef HAVE_FFS + +/* Define to 1 if you have the `getopt' function. */ +#undef HAVE_GETOPT + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBGEN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MALLOC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `mkstemp' function. */ +#undef HAVE_MKSTEMP + +/* Define to 1 if you have the `snprintf' function. */ +#undef HAVE_SNPRINTF + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strlcat' function. */ +#undef HAVE_STRLCAT + +/* Define to 1 if you have the `strlcpy' function. */ +#undef HAVE_STRLCPY + +/* Define to 1 if you have the `strtold' function. */ +#undef HAVE_STRTOLD + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#undef HAVE_SYS_WAIT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `vfork' function. */ +#undef HAVE_VFORK + +/* Define to 1 if you have the `vsnprintf' function. */ +#undef HAVE_VSNPRINTF + +/* Define if host is BIG endian */ +#undef HOST_BIG_ENDIAN + +/* Define if host is LITTLE endian */ +#undef HOST_LITTLE_ENDIAN + +/* lex is flex */ +#undef ISFLEX + +/* Define alternate standard lib directory */ +#undef LIBDIR + +/* Define path to alternate linker */ +#undef LINKER + +/* Using Mach-O ABI */ +#undef MACHOABI + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Major version no */ +#undef PCC_MAJOR + +/* Minor version no */ +#undef PCC_MINOR + +/* Minor minor version no */ +#undef PCC_MINORMINOR + +/* Using PE/COFF ABI */ +#undef PECOFFABI + +/* Define path to alternate preprocessor */ +#undef PREPROCESSOR + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define alternate standard include directory */ +#undef STDINC + +/* Define if target defaults to BIG endian */ +#undef TARGET_BIG_ENDIAN + +/* Define if target defaults to LITTLE endian */ +#undef TARGET_LITTLE_ENDIAN + +/* Target OS */ +#undef TARGOS + +/* Target OS version */ +#undef TARGOSVER + +/* Enable thread-local storage (TLS). */ +#undef TLS + +/* Version string */ +#undef VERSSTR + +/* Size of wide character type */ +#undef WCHAR_SIZE + +/* Type to use for wide characters */ +#undef WCHAR_TYPE + +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a + `char[]'. */ +#undef YYTEXT_POINTER diff --git a/compilers/pcc/pcc-1.0.0/config.sub b/compilers/pcc/pcc-1.0.0/config.sub new file mode 100644 index 00000000..8739b992 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/config.sub @@ -0,0 +1,1658 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +# Free Software Foundation, Inc. + +timestamp='2008-01-16' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | mt \ + | msp430 \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | score \ + | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tile*) + basic_machine=tile-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* | -midnightbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/compilers/pcc/pcc-1.0.0/configure b/compilers/pcc/pcc-1.0.0/configure new file mode 100755 index 00000000..6ad1dab2 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/configure @@ -0,0 +1,6240 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.61 for pcc 1.0.0.RELEASE. +# +# Report bugs to <>. +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + +fi + + + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +as_nl=' +' +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# CDPATH. +$as_unset CDPATH + + +if test "x$CONFIG_SHELL" = x; then + if (eval ":") 2>/dev/null; then + as_have_required=yes +else + as_have_required=no +fi + + if test $as_have_required = yes && (eval ": +(as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=\$LINENO + as_lineno_2=\$LINENO + test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && + test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } +") 2> /dev/null; then + : +else + as_candidate_shells= + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + case $as_dir in + /*) + for as_base in sh bash ksh sh5; do + as_candidate_shells="$as_candidate_shells $as_dir/$as_base" + done;; + esac +done +IFS=$as_save_IFS + + + for as_shell in $as_candidate_shells $SHELL; do + # Try only shells that exist, to save several forks. + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { ("$as_shell") 2> /dev/null <<\_ASEOF +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + +fi + + +: +_ASEOF +}; then + CONFIG_SHELL=$as_shell + as_have_required=yes + if { "$as_shell" 2> /dev/null <<\_ASEOF +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + +fi + + +: +(as_func_return () { + (exit $1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = "$1" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test $exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } + +_ASEOF +}; then + break +fi + +fi + + done + + if test "x$CONFIG_SHELL" != x; then + for as_var in BASH_ENV ENV + do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + done + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} +fi + + + if test $as_have_required = no; then + echo This script requires a shell more modern than all the + echo shells that I found on your system. Please install a + echo modern shell, or manually run the script under such a + echo shell if you do have one. + { (exit 1); exit 1; } +fi + + +fi + +fi + + + +(eval "as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0") || { + echo No shell found that supports shell functions. + echo Please tell autoconf@gnu.org about your system, + echo including any error possibly output before this + echo message +} + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir +fi +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + + +exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Identity of this package. +PACKAGE_NAME='pcc' +PACKAGE_TARNAME='pcc' +PACKAGE_VERSION='1.0.0.RELEASE' +PACKAGE_STRING='pcc 1.0.0.RELEASE' +PACKAGE_BUGREPORT='' + +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='SHELL +PATH_SEPARATOR +PACKAGE_NAME +PACKAGE_TARNAME +PACKAGE_VERSION +PACKAGE_STRING +PACKAGE_BUGREPORT +exec_prefix +prefix +program_transform_name +bindir +sbindir +libexecdir +datarootdir +datadir +sysconfdir +sharedstatedir +localstatedir +includedir +oldincludedir +docdir +infodir +htmldir +dvidir +pdfdir +psdir +libdir +localedir +mandir +DEFS +ECHO_C +ECHO_N +ECHO_T +LIBS +build_alias +host_alias +target_alias +build +build_cpu +build_vendor +build_os +host +host_cpu +host_vendor +host_os +target +target_cpu +target_vendor +target_os +BINPREFIX +CC +CFLAGS +LDFLAGS +CPPFLAGS +ac_ct_CC +EXEEXT +OBJEXT +CC_FOR_BUILD +CPP +GREP +EGREP +SET_MAKE +INSTALL_PROGRAM +INSTALL_SCRIPT +INSTALL_DATA +YACC +YFLAGS +strip +LEX +LEX_OUTPUT_ROOT +LEXLIB +targos +targosver +targmach +ADD_CFLAGS +ADD_CPPFLAGS +LIBOBJS +LTLIBOBJS' +ac_subst_files='' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP +YACC +YFLAGS' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` + eval enable_$ac_feature=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` + eval enable_$ac_feature=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/[-.]/_/g'` + eval with_$ac_package=\$ac_optarg ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/[-.]/_/g'` + eval with_$ac_package=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute directory names. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; } +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + { echo "$as_me: error: Working directory cannot be determined" >&2 + { (exit 1); exit 1; }; } +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + { echo "$as_me: error: pwd does not report name of working directory" >&2 + { (exit 1); exit 1; }; } + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$0" || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2 + { (exit 1); exit 1; }; } + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures pcc 1.0.0.RELEASE to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/pcc] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] + --target=TARGET configure for building compilers for TARGET [HOST] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of pcc 1.0.0.RELEASE:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-tls Enable Thread-local storage (TLS). + --disable-gcc-compat Disable GCC compatibility + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-incdir= Specify the default include path. + --with-libdir= Specify the default library path. + --with-assembler= Specify alternate assember. + --with-linker= Specify alternate linker. + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + YACC The `Yet Another C Compiler' implementation to use. Defaults to + the first program found out of: `bison -y', `byacc', `yacc'. + YFLAGS The list of arguments that will be passed by default to $YACC. + This script will default YFLAGS to the empty string to avoid a + default value of `-d' given by some make applications. + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to <>. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +pcc configure 1.0.0.RELEASE +generated by GNU Autoconf 2.61 + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by pcc $as_me 1.0.0.RELEASE, which was +generated by GNU Autoconf 2.61. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args '$ac_arg'" + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 +echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + *) $as_unset $ac_var ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------------- ## +## File substitutions. ## +## ------------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -n "$CONFIG_SITE"; then + set x "$CONFIG_SITE" +elif test "x$prefix" != xNONE; then + set x "$prefix/share/config.site" "$prefix/etc/config.site" +else + set x "$ac_default_prefix/share/config.site" \ + "$ac_default_prefix/etc/config.site" +fi +shift +for ac_site_file +do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + + + + + + + + + + + + + + + + + + + + + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_config_headers="$ac_config_headers config.h" + + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5 +echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;} + { (exit 1); exit 1; }; } +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5 +echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;} + { (exit 1); exit 1; }; } + +{ echo "$as_me:$LINENO: checking build system type" >&5 +echo $ECHO_N "checking build system type... $ECHO_C" >&6; } +if test "${ac_cv_build+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 +echo "$as_me: error: cannot guess build type; you must specify one" >&2;} + { (exit 1); exit 1; }; } +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5 +echo "${ECHO_T}$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5 +echo "$as_me: error: invalid value of canonical build" >&2;} + { (exit 1); exit 1; }; };; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ echo "$as_me:$LINENO: checking host system type" >&5 +echo $ECHO_N "checking host system type... $ECHO_C" >&6; } +if test "${ac_cv_host+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;} + { (exit 1); exit 1; }; } +fi + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5 +echo "${ECHO_T}$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5 +echo "$as_me: error: invalid value of canonical host" >&2;} + { (exit 1); exit 1; }; };; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +{ echo "$as_me:$LINENO: checking target system type" >&5 +echo $ECHO_N "checking target system type... $ECHO_C" >&6; } +if test "${ac_cv_target+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "x$target_alias" = x; then + ac_cv_target=$ac_cv_host +else + ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&2;} + { (exit 1); exit 1; }; } +fi + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_target" >&5 +echo "${ECHO_T}$ac_cv_target" >&6; } +case $ac_cv_target in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical target" >&5 +echo "$as_me: error: invalid value of canonical target" >&2;} + { (exit 1); exit 1; }; };; +esac +target=$ac_cv_target +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_target +shift +target_cpu=$1 +target_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +target_os=$* +IFS=$ac_save_IFS +case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac + + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +test -n "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + +abi=unknown +endian=little +targosver=0 +tls=no +gcccompat=yes +# allowed: UNSIGNED (4-char u_int), INT (4-char int), SHORT (2-char u_short) +wchar_type=INT + +case "$target_os" in + + apple) + targos=apple + abi=classic68k + case "$target_cpu" in + m68k) targmach=m68k endian=big ;; + esac + ;; + + bsd) + targos=bsd + abi=aout + targmach=pdp11 + wchar_type=USHORT + ;; + + darwin*) + targos=darwin + abi=macho + case "$target_os" in + *10.*) targosver=10 ;; + *9.*) targosver=9 ;; + *8.*) targosver=8 ;; + *7.*) targosver=7 ;; + esac + case "$target_cpu" in + i?86) targmach=i386 ;; + powerpc) targmach=powerpc endian=big ;; + x86_64) targmach=amd64 ;; + esac + ;; + + dragonfly*) + targos=dragonfly + abi=elf + tls=yes + case "$target_cpu" in + i?86) targmach=i386 ;; + x86_64) targmach=amd64 ;; + esac + ;; + + freebsd*) + targos=freebsd + abi=elf + case "$target_os" in + *9.*) targosver=9 ;; + *8.*) targosver=8 ;; + *7.*) targosver=7 ;; + *6.*) targosver=6 ;; + *5.*) targosver=5 ;; + *4.*) targosver=4 ;; + esac + case "$target_cpu" in + i386) targmach=i386 ;; + x86_64) targmach=amd64 ;; + esac + ;; + + linux*) + targos=linux + abi=elf + case "$target_cpu" in + i?86) targmach=i386 ;; + powerpc*) targmach=powerpc endian=big ;; + x86_64) targmach=amd64 ;; + mipseb) targmach=mips endian=big ;; + mips*) targmach=mips ;; + esac + ;; + + midnightbsd*) + targos=midnightbsd + abi=elf + case "$target_cpu" in + i?86) targmach=i386 ;; + sparc64) targmach=sparc64 endian=big ;; + esac + ;; + + mingw*) + targos=win32 + abi=pecoff + wchar_type=USHORT + targmach=i386 + altincdir="c:/mingw/include" + altlibdir="c:/mingw/lib" + ;; + + minix) + targos=minix + abi=coff + case "$target_cpu" in + m68k) targmach=m68k endian=big ;; + esac + ;; + + mirbsd*) + targos=mirbsd + abi=elf + wchar_type=USHORT + case "$target_cpu" in + i?86) targmach=i386 ;; + esac + ;; + + netbsd*) + targos=netbsd + abi=elf + case "$target_os" in + *5.*) targosver=5 ;; + *4.*) targosver=4 ;; + *3.*) targosver=3 ;; + *2.*) targosver=2 ;; + *1.*) targosver=1 ;; + esac + case "$target_cpu" in + armeb) targmach=arm endian=big ;; + arm*) targmach=arm ;; + i?86) targmach=i386 ;; + m68k*) targmach=m68k endian=big ;; + mipseb) targmach=mips endian=big ;; + mips*) targmach=mips ;; + pdp10) targmach=pdp10 ;; + powerpc) targmach=powerpc endian=big ;; + sparc64) targmach=sparc64 endian=big ;; + vax) targmach=vax ;; + x86_64) targmach=amd64 ;; + esac + ;; + + nextstep*) + targos=nextstep + abi=macho + case "$target_cpu" in + i?86) targmach=i386 ;; + sparc) targmach=sparc endian=big ;; + hppa) targmach=hppa endian=big ;; + esac + ;; + + openbsd*) + targos=openbsd + abi=elf + case "$target_cpu" in + i?86) targmach=i386 ;; + vax) targmach=vax ;; + powerpc) targmach=powerpc endian=big ;; + sparc64) targmach=sparc64 endian=big ;; + x86_64) targmach=amd64 ;; + esac + ;; + + sunos*|solaris*) + targos=sunos + abi=elf + case "$target_cpu" in + i?86) targmach=i386 ;; + sparc*) targmach=sparc64 endian=big ;; + esac + ;; + + windows*|pe*) + target_alias=i386-pe + targos=win32 + abi=pecoff + wchar_type=USHORT + targmach=i386 + ;; + + *) + targos="$target_os" + case "$target_cpu" in + m16c) targmach=m16c ;; + nova) targmach=nova ;; + esac + ;; +esac + +if test "X$targos" = X -o "X$targmach" = X ; then + { { echo "$as_me:$LINENO: error: '$target' is not (yet) supported by pcc." >&5 +echo "$as_me: error: '$target' is not (yet) supported by pcc." >&2;} + { (exit 1); exit 1; }; } +fi + +case "$host_os" in + + pe*) + # quick hack for cross-build to win32 host + if "$prefix" = NONE; then + prefix="c:/pcc" + assembler="yasm.exe -p gnu -f win32" + linker="link.exe /nologo" + ADD_CFLAGS=-DMSLINKER + fi + ;; + + sunos*|solaris*) + ADD_CPPFLAGS="$ADD_CPPFLAGS -D_XOPEN_SOURCE=600" + ;; + + darwin*) + if test "$targosver" -ge 10 ; then + targmach=amd64 + fi + ;; + +esac + +if test "X$endian" = "Xbig" ; then + +cat >>confdefs.h <<\_ACEOF +#define TARGET_BIG_ENDIAN 1 +_ACEOF + +else + +cat >>confdefs.h <<\_ACEOF +#define TARGET_LITTLE_ENDIAN 1 +_ACEOF + +fi + +case "$abi" in + elf*) +cat >>confdefs.h <<\_ACEOF +#define ELFABI +_ACEOF + ;; + aout) +cat >>confdefs.h <<\_ACEOF +#define AOUTABI +_ACEOF + ;; + macho) +cat >>confdefs.h <<\_ACEOF +#define MACHOABI +_ACEOF + ;; + coff) +cat >>confdefs.h <<\_ACEOF +#define COFFABI +_ACEOF + ;; + ecoff) +cat >>confdefs.h <<\_ACEOF +#define ECOFFABI +_ACEOF + ;; + pecoff) +cat >>confdefs.h <<\_ACEOF +#define PECOFFABI +_ACEOF + ;; + classic68k) +cat >>confdefs.h <<\_ACEOF +#define CLASSIC68K +_ACEOF + ;; +esac + +# Specify alternate assembler, linker, include and lib paths + +# Check whether --with-incdir was given. +if test "${with_incdir+set}" = set; then + withval=$with_incdir; altincdir=$withval +fi + + +# Check whether --with-libdir was given. +if test "${with_libdir+set}" = set; then + withval=$with_libdir; altlibdir=$withval +fi + + +# Check whether --with-assembler was given. +if test "${with_assembler+set}" = set; then + withval=$with_assembler; assembler=$withval +fi + + +# Check whether --with-linker was given. +if test "${with_linker+set}" = set; then + withval=$with_linker; linker=$withval +fi + +# Check whether --enable-tls was given. +if test "${enable_tls+set}" = set; then + enableval=$enable_tls; tls=$enableval +fi + +if test "$tls" = "yes"; then + +cat >>confdefs.h <<\_ACEOF +#define TLS 1 +_ACEOF + +fi +# Check whether --enable-gcc-compat was given. +if test "${enable_gcc_compat+set}" = set; then + enableval=$enable_gcc_compat; gcccompat=$enableval +fi + +if test "$gcccompat" = "yes"; then + ADD_CPPFLAGS="$ADD_CPPFLAGS -DGCC_COMPAT"; +fi + +# setup for building a cross-compiler +if test "X$target_alias" = "X$host_alias" -o "X$target_alias" = "X"; then + BINPREFIX="" +else + BINPREFIX="${target_alias}-" + test "X$prefix" = XNONE && prefix="$ac_default_prefix" + test "X$exec_prefix" = XNONE && exec_prefix="${prefix}" + if test -z "$altincdir"; then + altincdir=${exec_prefix}/${target_alias}/include + fi + if test -z "$altlibdir"; then + altlibdir=${exec_prefix}/${target_alias}/lib + fi + if test -z "$assembler"; then + assembler=${BINPREFIX}as + fi + if test -z "$linker"; then + linker=${BINPREFIX}ld + fi + preprocessor="${BINPREFIX}cpp" + compiler="${BINPREFIX}ccom" +fi + + +if test -n "$altincdir"; then + +cat >>confdefs.h <<_ACEOF +#define STDINC "$altincdir" +_ACEOF + +fi +if test -n "$altlibdir"; then + +cat >>confdefs.h <<_ACEOF +#define LIBDIR "${altlibdir}/" +_ACEOF + +fi +if test -n "$assembler"; then + +cat >>confdefs.h <<_ACEOF +#define ASSEMBLER "$assembler" +_ACEOF + +fi +if test -n "$linker"; then + +cat >>confdefs.h <<_ACEOF +#define LINKER "$linker" +_ACEOF + +fi +if test -n "$preprocessor"; then + +cat >>confdefs.h <<_ACEOF +#define PREPROCESSOR "${BINPREFIX}cpp" +_ACEOF + +fi +if test -n "$compiler"; then + +cat >>confdefs.h <<_ACEOF +#define COMPILER "${BINPREFIX}ccom" +_ACEOF + +fi + +case $wchar_type in +USHORT) wchar_size=2 ;; +UNSIGNED|INT) wchar_size=4 ;; +*) { { echo "$as_me:$LINENO: error: Unknown wchar_t '$wchar_type'." >&5 +echo "$as_me: error: Unknown wchar_t '$wchar_type'." >&2;} + { (exit 1); exit 1; }; } ;; +esac + + +cat >>confdefs.h <<_ACEOF +#define WCHAR_TYPE $wchar_type +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define WCHAR_SIZE $wchar_size +_ACEOF + + +# check for additional compiler flags +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; } +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +# +# List of possible output files, starting from the most likely. +# The algorithm is not robust to junk in `.', hence go to wildcards (a.*) +# only as a last resort. b.out is created by i960 compilers. +ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out' +# +# The IRIX 6 linker writes into existing files which may not be +# executable, retaining their permissions. Remove them first so a +# subsequent execution test works. +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { (ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi + +{ echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6; } +if test -z "$ac_file"; then + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext + +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; } +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +{ echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; } +{ echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6; } + +{ echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; } +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +{ echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; } +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 +echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_c89=$ac_arg +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6; } ;; + xno) + { echo "$as_me:$LINENO: result: unsupported" >&5 +echo "${ECHO_T}unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; +esac + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +DESIRED_FLAGS="-Wall -Wmissing-prototypes -Wstrict-prototypes -Wshadow -Wsign-compare -Wtruncate" +for flag in $DESIRED_FLAGS +do + { echo "$as_me:$LINENO: checking whether $CC accepts $flag" >&5 +echo $ECHO_N "checking whether $CC accepts $flag... $ECHO_C" >&6; } + cat >conftest.$ac_ext <<_ACEOF +int main() { return 0; } +_ACEOF + $CC $CFLAGS $flag -c conftest.c > /dev/null 2> /dev/null + if test $? = 0 ; then + ADD_CFLAGS="$ADD_CFLAGS $flag" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; }; + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; }; + fi + rm -f conftest.o +done + +# setup for cross-compiling mkext +{ echo "$as_me:$LINENO: checking for a C compiler for mkext" >&5 +echo $ECHO_N "checking for a C compiler for mkext... $ECHO_C" >&6; } +if test $cross_compiling = yes; then + { echo "$as_me:$LINENO: result: cross compiling" >&5 +echo "${ECHO_T}cross compiling" >&6; } + for ac_prog in pcc gcc cc +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC_FOR_BUILD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC_FOR_BUILD"; then + ac_cv_prog_CC_FOR_BUILD="$CC_FOR_BUILD" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC_FOR_BUILD="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC_FOR_BUILD=$ac_cv_prog_CC_FOR_BUILD +if test -n "$CC_FOR_BUILD"; then + { echo "$as_me:$LINENO: result: $CC_FOR_BUILD" >&5 +echo "${ECHO_T}$CC_FOR_BUILD" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$CC_FOR_BUILD" && break +done + +else + { echo "$as_me:$LINENO: result: not cross compiling" >&5 +echo "${ECHO_T}not cross compiling" >&6; } + CC_FOR_BUILD=${CC-cc} + +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 +echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; } +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Extract the first word of "grep ggrep" to use in msg output +if test -z "$GREP"; then +set dummy grep ggrep; ac_prog_name=$2 +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_path_GREP_found=false +# Loop through the user's path and test for each of PROGNAME-LIST +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue + # Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + ac_count=`expr $ac_count + 1` + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + + $ac_path_GREP_found && break 3 + done +done + +done +IFS=$as_save_IFS + + +fi + +GREP="$ac_cv_path_GREP" +if test -z "$GREP"; then + { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } +fi + +else + ac_cv_path_GREP=$GREP +fi + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 +echo "${ECHO_T}$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6; } +if test "${ac_cv_path_EGREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + # Extract the first word of "egrep" to use in msg output +if test -z "$EGREP"; then +set dummy egrep; ac_prog_name=$2 +if test "${ac_cv_path_EGREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_path_EGREP_found=false +# Loop through the user's path and test for each of PROGNAME-LIST +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue + # Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + ac_count=`expr $ac_count + 1` + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + + $ac_path_EGREP_found && break 3 + done +done + +done +IFS=$as_save_IFS + + +fi + +EGREP="$ac_cv_path_EGREP" +if test -z "$EGREP"; then + { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } +fi + +else + ac_cv_path_EGREP=$EGREP +fi + + + fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 +echo "${ECHO_T}$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_stdc=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +{ echo "$as_me:$LINENO: checking for C99 printf size specifiers" >&5 +echo $ECHO_N "checking for C99 printf size specifiers... $ECHO_C" >&6; } +if test "${ac_have_c99_format+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + ac_have_c99_format=yes +else + cat >conftest.$ac_ext <<_ACEOF + + /* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + char buf[64]; + if (sprintf(buf, "%lld%hhd%jd%zd%td", (long long int)1, (char)2, (intmax_t)3, (size_t)4, (ptrdiff_t)5) != 5) + exit(1); + else if (strcmp(buf, "12345")) + exit(2); + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_have_c99_format=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) + ac_have_c99_format=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + +fi +{ echo "$as_me:$LINENO: result: $ac_have_c99_format" >&5 +echo "${ECHO_T}$ac_have_c99_format" >&6; } +if test $ac_have_c99_format = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_C99_FORMAT 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for C99 variadic macro support" >&5 +echo $ECHO_N "checking for C99 variadic macro support... $ECHO_C" >&6; } +if test "${ac_have_variadic+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF + + #define macro(...) func(__VA_ARGS__) + int func(int a, ...); + int test() { return macro(1, 2, 3); } + +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_have_variadic=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_have_variadic=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_have_variadic" >&5 +echo "${ECHO_T}$ac_have_variadic" >&6; } +if test $ac_have_variadic = yes ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_CPP_VARARG_MACRO_GCC 1 +_ACEOF + +fi + +# Byteorder of host +{ echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 +echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6; } +if test "${ac_cv_c_bigendian+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # See if sys/param.h defines the BYTE_ORDER macro. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN && defined LITTLE_ENDIAN \ + && BYTE_ORDER && BIG_ENDIAN && LITTLE_ENDIAN) + bogus endian macros +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + # It does; now see whether it defined to BIG_ENDIAN or not. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_c_bigendian=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_c_bigendian=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # It does not; compile a test program. +if test "$cross_compiling" = yes; then + # try to guess the endianness by grepping values into an object file + ac_cv_c_bigendian=unknown + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; +short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; +void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } +short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; +short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; +void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } +int +main () +{ + _ascii (); _ebcdic (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then + ac_cv_c_bigendian=yes +fi +if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi +fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=no +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 +echo "${ECHO_T}$ac_cv_c_bigendian" >&6; } +case $ac_cv_c_bigendian in + yes) + +cat >>confdefs.h <<\_ACEOF +#define HOST_BIG_ENDIAN +_ACEOF + ;; + no) + +cat >>confdefs.h <<\_ACEOF +#define HOST_LITTLE_ENDIAN +_ACEOF + ;; + *) + { { echo "$as_me:$LINENO: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&5 +echo "$as_me: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} + { (exit 1); exit 1; }; } ;; +esac + + + +# Checks for programs. +{ echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; } +set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + SET_MAKE= +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; } +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done +IFS=$as_save_IFS + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +for ac_prog in 'bison -y' byacc +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_YACC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$YACC"; then + ac_cv_prog_YACC="$YACC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_YACC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +YACC=$ac_cv_prog_YACC +if test -n "$YACC"; then + { echo "$as_me:$LINENO: result: $YACC" >&5 +echo "${ECHO_T}$YACC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$YACC" && break +done +test -n "$YACC" || YACC="yacc" + +# Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_strip+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$strip"; then + ac_cv_prog_strip="$strip" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_strip="yes" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_strip" && ac_cv_prog_strip="no" +fi +fi +strip=$ac_cv_prog_strip +if test -n "$strip"; then + { echo "$as_me:$LINENO: result: $strip" >&5 +echo "${ECHO_T}$strip" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + +for ac_prog in flex lex +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_LEX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$LEX"; then + ac_cv_prog_LEX="$LEX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_LEX="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +LEX=$ac_cv_prog_LEX +if test -n "$LEX"; then + { echo "$as_me:$LINENO: result: $LEX" >&5 +echo "${ECHO_T}$LEX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$LEX" && break +done +test -n "$LEX" || LEX=":" + +if test "x$LEX" != "x:"; then + cat >conftest.l <<_ACEOF +%% +a { ECHO; } +b { REJECT; } +c { yymore (); } +d { yyless (1); } +e { yyless (input () != 0); } +f { unput (yytext[0]); } +. { BEGIN INITIAL; } +%% +#ifdef YYTEXT_POINTER +extern char *yytext; +#endif +int +main (void) +{ + return ! yylex () + ! yywrap (); +} +_ACEOF +{ (ac_try="$LEX conftest.l" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$LEX conftest.l") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ echo "$as_me:$LINENO: checking lex output file root" >&5 +echo $ECHO_N "checking lex output file root... $ECHO_C" >&6; } +if test "${ac_cv_prog_lex_root+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + +if test -f lex.yy.c; then + ac_cv_prog_lex_root=lex.yy +elif test -f lexyy.c; then + ac_cv_prog_lex_root=lexyy +else + { { echo "$as_me:$LINENO: error: cannot find output from $LEX; giving up" >&5 +echo "$as_me: error: cannot find output from $LEX; giving up" >&2;} + { (exit 1); exit 1; }; } +fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_lex_root" >&5 +echo "${ECHO_T}$ac_cv_prog_lex_root" >&6; } +LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root + +if test -z "${LEXLIB+set}"; then + { echo "$as_me:$LINENO: checking lex library" >&5 +echo $ECHO_N "checking lex library... $ECHO_C" >&6; } +if test "${ac_cv_lib_lex+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + ac_save_LIBS=$LIBS + ac_cv_lib_lex='none needed' + for ac_lib in '' -lfl -ll; do + LIBS="$ac_lib $ac_save_LIBS" + cat >conftest.$ac_ext <<_ACEOF +`cat $LEX_OUTPUT_ROOT.c` +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_lex=$ac_lib +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + test "$ac_cv_lib_lex" != 'none needed' && break + done + LIBS=$ac_save_LIBS + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_lex" >&5 +echo "${ECHO_T}$ac_cv_lib_lex" >&6; } + test "$ac_cv_lib_lex" != 'none needed' && LEXLIB=$ac_cv_lib_lex +fi + + +{ echo "$as_me:$LINENO: checking whether yytext is a pointer" >&5 +echo $ECHO_N "checking whether yytext is a pointer... $ECHO_C" >&6; } +if test "${ac_cv_prog_lex_yytext_pointer+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # POSIX says lex can declare yytext either as a pointer or an array; the +# default is implementation-dependent. Figure out which it is, since +# not all implementations provide the %pointer and %array declarations. +ac_cv_prog_lex_yytext_pointer=no +ac_save_LIBS=$LIBS +LIBS="$LEXLIB $ac_save_LIBS" +cat >conftest.$ac_ext <<_ACEOF +#define YYTEXT_POINTER 1 +`cat $LEX_OUTPUT_ROOT.c` +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_prog_lex_yytext_pointer=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_save_LIBS + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_lex_yytext_pointer" >&5 +echo "${ECHO_T}$ac_cv_prog_lex_yytext_pointer" >&6; } +if test $ac_cv_prog_lex_yytext_pointer = yes; then + +cat >>confdefs.h <<\_ACEOF +#define YYTEXT_POINTER 1 +_ACEOF + +fi +rm -f conftest.l $LEX_OUTPUT_ROOT.c + +fi +if test "$LEX" = flex ; then + +cat >>confdefs.h <<_ACEOF +#define ISFLEX 1 +_ACEOF + +fi + +# Checks for libraries. + +# Checks for header files. +# AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h]) + + + +for ac_header in string.h malloc.h libgen.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------------- ## +## Report this to ## +## ------------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +{ echo "$as_me:$LINENO: checking for sys/wait.h that is POSIX.1 compatible" >&5 +echo $ECHO_N "checking for sys/wait.h that is POSIX.1 compatible... $ECHO_C" >&6; } +if test "${ac_cv_header_sys_wait_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#ifndef WEXITSTATUS +# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) +#endif +#ifndef WIFEXITED +# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif + +int +main () +{ + int s; + wait (&s); + s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_sys_wait_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_sys_wait_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_wait_h" >&6; } +if test $ac_cv_header_sys_wait_h = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_SYS_WAIT_H 1 +_ACEOF + +fi + + +# Checks for library functions. +## AC_FUNC_STRTOD +# AC_FUNC_VPRINTF +# AC_CHECK_FUNCS([memset strchr strdup strrchr strtol]) + + + + + + + + + + +for ac_func in strtold vsnprintf snprintf mkstemp strlcat strlcpy basename getopt ffs vfork +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + + + + + + + + + + + + +pcc_major=`echo $PACKAGE_VERSION | awk -F. '{print $1}'` +pcc_minor=`echo $PACKAGE_VERSION | awk -F. '{print $2}'` +pcc_minorminor=`echo $PACKAGE_VERSION | awk -F. '{print $3}'` +versstr="\"$PACKAGE_STRING `cat $srcdir/DATESTAMP` for $target, $USER@`hostname`\"" + + +cat >>confdefs.h <<_ACEOF +#define TARGOS $targos +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define TARGOSVER $targosver +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PCC_MAJOR $pcc_major +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PCC_MINOR $pcc_minor +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PCC_MINORMINOR $pcc_minorminor +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSSTR $versstr +_ACEOF + + +ac_config_files="$ac_config_files Makefile cc/Makefile cc/cc/Makefile cc/cpp/Makefile cc/ccom/Makefile f77/Makefile f77/f77/Makefile f77/fcom/Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 +echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + *) $as_unset $ac_var ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + test "x$cache_file" != "x/dev/null" && + { echo "$as_me:$LINENO: updating cache $cache_file" >&5 +echo "$as_me: updating cache $cache_file" >&6;} + cat confcache >$cache_file + else + { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 +echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + +fi + + + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +as_nl=' +' +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# CDPATH. +$as_unset CDPATH + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir +fi +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 + +# Save the log message, to keep $[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by pcc $as_me 1.0.0.RELEASE, which was +generated by GNU Autoconf 2.61. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +pcc config.status 1.0.0.RELEASE +configured by $0, generated by GNU Autoconf 2.61, + with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2006 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + echo "$ac_cs_version"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + { echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + CONFIG_SHELL=$SHELL + export CONFIG_SHELL + exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "cc/Makefile") CONFIG_FILES="$CONFIG_FILES cc/Makefile" ;; + "cc/cc/Makefile") CONFIG_FILES="$CONFIG_FILES cc/cc/Makefile" ;; + "cc/cpp/Makefile") CONFIG_FILES="$CONFIG_FILES cc/cpp/Makefile" ;; + "cc/ccom/Makefile") CONFIG_FILES="$CONFIG_FILES cc/ccom/Makefile" ;; + "f77/Makefile") CONFIG_FILES="$CONFIG_FILES f77/Makefile" ;; + "f77/f77/Makefile") CONFIG_FILES="$CONFIG_FILES f77/f77/Makefile" ;; + "f77/fcom/Makefile") CONFIG_FILES="$CONFIG_FILES f77/fcom/Makefile" ;; + + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= + trap 'exit_status=$? + { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status +' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +# +# Set up the sed scripts for CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "$CONFIG_FILES"; then + +_ACEOF + + + +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + cat >conf$$subs.sed <<_ACEOF +SHELL!$SHELL$ac_delim +PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim +PACKAGE_NAME!$PACKAGE_NAME$ac_delim +PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim +PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim +PACKAGE_STRING!$PACKAGE_STRING$ac_delim +PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim +exec_prefix!$exec_prefix$ac_delim +prefix!$prefix$ac_delim +program_transform_name!$program_transform_name$ac_delim +bindir!$bindir$ac_delim +sbindir!$sbindir$ac_delim +libexecdir!$libexecdir$ac_delim +datarootdir!$datarootdir$ac_delim +datadir!$datadir$ac_delim +sysconfdir!$sysconfdir$ac_delim +sharedstatedir!$sharedstatedir$ac_delim +localstatedir!$localstatedir$ac_delim +includedir!$includedir$ac_delim +oldincludedir!$oldincludedir$ac_delim +docdir!$docdir$ac_delim +infodir!$infodir$ac_delim +htmldir!$htmldir$ac_delim +dvidir!$dvidir$ac_delim +pdfdir!$pdfdir$ac_delim +psdir!$psdir$ac_delim +libdir!$libdir$ac_delim +localedir!$localedir$ac_delim +mandir!$mandir$ac_delim +DEFS!$DEFS$ac_delim +ECHO_C!$ECHO_C$ac_delim +ECHO_N!$ECHO_N$ac_delim +ECHO_T!$ECHO_T$ac_delim +LIBS!$LIBS$ac_delim +build_alias!$build_alias$ac_delim +host_alias!$host_alias$ac_delim +target_alias!$target_alias$ac_delim +build!$build$ac_delim +build_cpu!$build_cpu$ac_delim +build_vendor!$build_vendor$ac_delim +build_os!$build_os$ac_delim +host!$host$ac_delim +host_cpu!$host_cpu$ac_delim +host_vendor!$host_vendor$ac_delim +host_os!$host_os$ac_delim +target!$target$ac_delim +target_cpu!$target_cpu$ac_delim +target_vendor!$target_vendor$ac_delim +target_os!$target_os$ac_delim +BINPREFIX!$BINPREFIX$ac_delim +CC!$CC$ac_delim +CFLAGS!$CFLAGS$ac_delim +LDFLAGS!$LDFLAGS$ac_delim +CPPFLAGS!$CPPFLAGS$ac_delim +ac_ct_CC!$ac_ct_CC$ac_delim +EXEEXT!$EXEEXT$ac_delim +OBJEXT!$OBJEXT$ac_delim +CC_FOR_BUILD!$CC_FOR_BUILD$ac_delim +CPP!$CPP$ac_delim +GREP!$GREP$ac_delim +EGREP!$EGREP$ac_delim +SET_MAKE!$SET_MAKE$ac_delim +INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim +INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim +INSTALL_DATA!$INSTALL_DATA$ac_delim +YACC!$YACC$ac_delim +YFLAGS!$YFLAGS$ac_delim +strip!$strip$ac_delim +LEX!$LEX$ac_delim +LEX_OUTPUT_ROOT!$LEX_OUTPUT_ROOT$ac_delim +LEXLIB!$LEXLIB$ac_delim +targos!$targos$ac_delim +targosver!$targosver$ac_delim +targmach!$targmach$ac_delim +ADD_CFLAGS!$ADD_CFLAGS$ac_delim +ADD_CPPFLAGS!$ADD_CPPFLAGS$ac_delim +LIBOBJS!$LIBOBJS$ac_delim +LTLIBOBJS!$LTLIBOBJS$ac_delim +_ACEOF + + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 78; then + break + elif $ac_last_try; then + { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` +if test -n "$ac_eof"; then + ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` + ac_eof=`expr $ac_eof + 1` +fi + +cat >>$CONFIG_STATUS <<_ACEOF +cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end +_ACEOF +sed ' +s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g +s/^/s,@/; s/!/@,|#_!!_#|/ +:n +t n +s/'"$ac_delim"'$/,g/; t +s/$/\\/; p +N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n +' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF +:end +s/|#_!!_#|//g +CEOF$ac_eof +_ACEOF + + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ +s/:*$// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF +fi # test -n "$CONFIG_FILES" + + +for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 +echo "$as_me: error: Invalid tag $ac_tag." >&2;} + { (exit 1); exit 1; }; };; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 +echo "$as_me: error: cannot find input file: $ac_f" >&2;} + { (exit 1); exit 1; }; };; + esac + ac_file_inputs="$ac_file_inputs $ac_f" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input="Generated from "`IFS=: + echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + fi + + case $ac_tag in + *:-:* | *:-) cat >"$tmp/stdin";; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + { as_dir="$ac_dir" + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 +echo "$as_me: error: cannot create directory $as_dir" >&2;} + { (exit 1); exit 1; }; }; } + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= + +case `sed -n '/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p +' $ac_file_inputs` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s&@configure_input@&$configure_input&;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +$ac_datarootdir_hack +" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&5 +echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&2;} + + rm -f "$tmp/stdin" + case $ac_file in + -) cat "$tmp/out"; rm -f "$tmp/out";; + *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; + esac + ;; + :H) + # + # CONFIG_HEADER + # +_ACEOF + +# Transform confdefs.h into a sed script `conftest.defines', that +# substitutes the proper values into config.h.in to produce config.h. +rm -f conftest.defines conftest.tail +# First, append a space to every undef/define line, to ease matching. +echo 's/$/ /' >conftest.defines +# Then, protect against being on the right side of a sed subst, or in +# an unquoted here document, in config.status. If some macros were +# called several times there might be several #defines for the same +# symbol, which is useless. But do not sort them, since the last +# AC_DEFINE must be honored. +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where +# NAME is the cpp macro being defined, VALUE is the value it is being given. +# PARAMS is the parameter list in the macro definition--in most cases, it's +# just an empty string. +ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*' +ac_dB='\\)[ (].*,\\1define\\2' +ac_dC=' ' +ac_dD=' ,' + +uniq confdefs.h | + sed -n ' + t rset + :rset + s/^[ ]*#[ ]*define[ ][ ]*// + t ok + d + :ok + s/[\\&,]/\\&/g + s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p + s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p + ' >>conftest.defines + +# Remove the space that was appended to ease matching. +# Then replace #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +# (The regexp can be short, since the line contains either #define or #undef.) +echo 's/ $// +s,^[ #]*u.*,/* & */,' >>conftest.defines + +# Break up conftest.defines: +ac_max_sed_lines=50 + +# First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1" +# Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2" +# Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1" +# et cetera. +ac_in='$ac_file_inputs' +ac_out='"$tmp/out1"' +ac_nxt='"$tmp/out2"' + +while : +do + # Write a here document: + cat >>$CONFIG_STATUS <<_ACEOF + # First, check the format of the line: + cat >"\$tmp/defines.sed" <<\\CEOF +/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def +/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def +b +:def +_ACEOF + sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS + ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in + sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail + grep . conftest.tail >/dev/null || break + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines conftest.tail + +echo "ac_result=$ac_in" >>$CONFIG_STATUS +cat >>$CONFIG_STATUS <<\_ACEOF + if test x"$ac_file" != x-; then + echo "/* $configure_input */" >"$tmp/config.h" + cat "$ac_result" >>"$tmp/config.h" + if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f $ac_file + mv "$tmp/config.h" $ac_file + fi + else + echo "/* $configure_input */" + cat "$ac_result" + fi + rm -f "$tmp/out12" + ;; + + + esac + +done # for ac_tag + + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + + +eval "exec_prefix=$exec_prefix" +eval "bindir=$bindir" +eval "libexecdir=$libexecdir" + +echo +echo "Target CPU is .................... ${targmach}" +echo "Target ABI is .................... ${abi}" +echo "Target OS is ..................... ${targos}" +echo "Compiler is called ............... ${BINPREFIX}pcc${EXEEXT}" +echo "Installing compiler into ......... ${bindir}" +echo "Installing pre-processor into .... ${libexecdir}" +echo "Using assembler .................. ${assembler-}" +echo "Using linker ..................... ${linker-}" +echo "Using include path ............... ${altincdir-}" +echo "Using library path ............... ${altlibdir-}" +echo "Has TLS support .................. $tls" +echo "Has GCC compatibility ............ $gcccompat" +echo "Type of wchar_t is ............... ${wchar_type} (${wchar_size} chars)" +echo +echo "Configure finished. Do 'make && make install' to compile and install. +" diff --git a/compilers/pcc/pcc-1.0.0/configure.ac b/compilers/pcc/pcc-1.0.0/configure.ac new file mode 100644 index 00000000..6bd80263 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/configure.ac @@ -0,0 +1,482 @@ + -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.59) +AC_INIT([pcc], [1.0.0.RELEASE], ) +AC_CONFIG_HEADER([config.h]) + +AC_CANONICAL_TARGET + +abi=unknown +endian=little +targosver=0 +tls=no +gcccompat=yes +# allowed: UNSIGNED (4-char u_int), INT (4-char int), SHORT (2-char u_short) +wchar_type=INT + +case "$target_os" in + + apple) + targos=apple + abi=classic68k + case "$target_cpu" in + m68k) targmach=m68k endian=big ;; + esac + ;; + + bsd) + targos=bsd + abi=aout + targmach=pdp11 + wchar_type=USHORT + ;; + + darwin*) + targos=darwin + abi=macho + case "$target_os" in + *10.*) targosver=10 ;; + *9.*) targosver=9 ;; + *8.*) targosver=8 ;; + *7.*) targosver=7 ;; + esac + case "$target_cpu" in + i?86) targmach=i386 ;; + powerpc) targmach=powerpc endian=big ;; + x86_64) targmach=amd64 ;; + esac + ;; + + dragonfly*) + targos=dragonfly + abi=elf + tls=yes + case "$target_cpu" in + i?86) targmach=i386 ;; + x86_64) targmach=amd64 ;; + esac + ;; + + freebsd*) + targos=freebsd + abi=elf + case "$target_os" in + *9.*) targosver=9 ;; + *8.*) targosver=8 ;; + *7.*) targosver=7 ;; + *6.*) targosver=6 ;; + *5.*) targosver=5 ;; + *4.*) targosver=4 ;; + esac + case "$target_cpu" in + i386) targmach=i386 ;; + x86_64) targmach=amd64 ;; + esac + ;; + + linux*) + targos=linux + abi=elf + case "$target_cpu" in + i?86) targmach=i386 ;; + powerpc*) targmach=powerpc endian=big ;; + x86_64) targmach=amd64 ;; + mipseb) targmach=mips endian=big ;; + mips*) targmach=mips ;; + esac + ;; + + midnightbsd*) + targos=midnightbsd + abi=elf + case "$target_cpu" in + i?86) targmach=i386 ;; + sparc64) targmach=sparc64 endian=big ;; + esac + ;; + + mingw*) + targos=win32 + abi=pecoff + wchar_type=USHORT + targmach=i386 + altincdir="c:/mingw/include" + altlibdir="c:/mingw/lib" + ;; + + minix) + targos=minix + abi=coff + case "$target_cpu" in + m68k) targmach=m68k endian=big ;; + esac + ;; + + mirbsd*) + targos=mirbsd + abi=elf + wchar_type=USHORT + case "$target_cpu" in + i?86) targmach=i386 ;; + esac + ;; + + netbsd*) + targos=netbsd + abi=elf + case "$target_os" in + *5.*) targosver=5 ;; + *4.*) targosver=4 ;; + *3.*) targosver=3 ;; + *2.*) targosver=2 ;; + *1.*) targosver=1 ;; + esac + case "$target_cpu" in + armeb) targmach=arm endian=big ;; + arm*) targmach=arm ;; + i?86) targmach=i386 ;; + m68k*) targmach=m68k endian=big ;; + mipseb) targmach=mips endian=big ;; + mips*) targmach=mips ;; + pdp10) targmach=pdp10 ;; + powerpc) targmach=powerpc endian=big ;; + sparc64) targmach=sparc64 endian=big ;; + vax) targmach=vax ;; + x86_64) targmach=amd64 ;; + esac + ;; + + nextstep*) + targos=nextstep + abi=macho + case "$target_cpu" in + i?86) targmach=i386 ;; + sparc) targmach=sparc endian=big ;; + hppa) targmach=hppa endian=big ;; + esac + ;; + + openbsd*) + targos=openbsd + abi=elf + case "$target_cpu" in + i?86) targmach=i386 ;; + vax) targmach=vax ;; + powerpc) targmach=powerpc endian=big ;; + sparc64) targmach=sparc64 endian=big ;; + x86_64) targmach=amd64 ;; + esac + ;; + + sunos*|solaris*) + targos=sunos + abi=elf + case "$target_cpu" in + i?86) targmach=i386 ;; + sparc*) targmach=sparc64 endian=big ;; + esac + ;; + + windows*|pe*) + target_alias=i386-pe + targos=win32 + abi=pecoff + wchar_type=USHORT + targmach=i386 + ;; + + *) + targos="$target_os" + case "$target_cpu" in + m16c) targmach=m16c ;; + nova) targmach=nova ;; + esac + ;; +esac + +if test "X$targos" = X -o "X$targmach" = X ; then + AC_MSG_ERROR(['$target' is not (yet) supported by pcc.]) +fi + +case "$host_os" in + + pe*) + # quick hack for cross-build to win32 host + if "$prefix" = NONE; then + prefix="c:/pcc" + assembler="yasm.exe -p gnu -f win32" + linker="link.exe /nologo" + ADD_CFLAGS=-DMSLINKER + fi + ;; + + sunos*|solaris*) + ADD_CPPFLAGS="$ADD_CPPFLAGS -D_XOPEN_SOURCE=600" + ;; + + darwin*) + if test "$targosver" -ge 10 ; then + targmach=amd64 + fi + ;; + +esac + +if test "X$endian" = "Xbig" ; then + AC_DEFINE(TARGET_BIG_ENDIAN, 1, + [Define if target defaults to BIG endian]) +else + AC_DEFINE(TARGET_LITTLE_ENDIAN, 1, + [Define if target defaults to LITTLE endian]) +fi + +case "$abi" in + elf*) AC_DEFINE(ELFABI, [], [Using ELF ABI]) ;; + aout) AC_DEFINE(AOUTABI, [], [Using a.out ABI]) ;; + macho) AC_DEFINE(MACHOABI, [], [Using Mach-O ABI]) ;; + coff) AC_DEFINE(COFFABI, [], [Using COFF ABI]) ;; + ecoff) AC_DEFINE(ECOFFABI, [], [Using ECOFF ABI]) ;; + pecoff) AC_DEFINE(PECOFFABI, [], [Using PE/COFF ABI]) ;; + classic68k) AC_DEFINE(CLASSIC68K, [], [Using Classic 68k ABI]) ;; +esac + +# Specify alternate assembler, linker, include and lib paths +AC_ARG_WITH(incdir, + AC_HELP_STRING([--with-incdir=], + [Specify the default include path.]), + altincdir=$withval, + []) +AC_ARG_WITH(libdir, + AC_HELP_STRING([--with-libdir=], + [Specify the default library path.]), + altlibdir=$withval, + []) +AC_ARG_WITH(assembler, + AC_HELP_STRING([--with-assembler=], + [Specify alternate assember.]), + assembler=$withval, + []) +AC_ARG_WITH(linker, + AC_HELP_STRING([--with-linker=], + [Specify alternate linker.]), + linker=$withval, + []) +AC_ARG_ENABLE(tls, + AC_HELP_STRING([--enable-tls], + [Enable Thread-local storage (TLS).]), + [tls=$enableval], []) +if test "$tls" = "yes"; then + AC_DEFINE(TLS, 1, [Enable thread-local storage (TLS).]) +fi +AC_ARG_ENABLE(gcc-compat, + AC_HELP_STRING([--disable-gcc-compat], + [Disable GCC compatibility]), + [gcccompat=$enableval], []) +if test "$gcccompat" = "yes"; then + ADD_CPPFLAGS="$ADD_CPPFLAGS -DGCC_COMPAT"; +fi + +# setup for building a cross-compiler +if test "X$target_alias" = "X$host_alias" -o "X$target_alias" = "X"; then + BINPREFIX="" +else + BINPREFIX="${target_alias}-" + test "X$prefix" = XNONE && prefix="$ac_default_prefix" + test "X$exec_prefix" = XNONE && exec_prefix="${prefix}" + if test -z "$altincdir"; then + altincdir=${exec_prefix}/${target_alias}/include + fi + if test -z "$altlibdir"; then + altlibdir=${exec_prefix}/${target_alias}/lib + fi + if test -z "$assembler"; then + assembler=${BINPREFIX}as + fi + if test -z "$linker"; then + linker=${BINPREFIX}ld + fi + preprocessor="${BINPREFIX}cpp" + compiler="${BINPREFIX}ccom" +fi +AC_SUBST(BINPREFIX) + +if test -n "$altincdir"; then + AC_DEFINE_UNQUOTED(STDINC, "$altincdir", + [Define alternate standard include directory]) +fi +if test -n "$altlibdir"; then + AC_DEFINE_UNQUOTED(LIBDIR, "${altlibdir}/", + [Define alternate standard lib directory]) +fi +if test -n "$assembler"; then + AC_DEFINE_UNQUOTED(ASSEMBLER, "$assembler", + [Define path to alternate assembler]) +fi +if test -n "$linker"; then + AC_DEFINE_UNQUOTED(LINKER, "$linker", + [Define path to alternate linker]) +fi +if test -n "$preprocessor"; then + AC_DEFINE_UNQUOTED(PREPROCESSOR, "${BINPREFIX}cpp", + [Define path to alternate preprocessor]) +fi +if test -n "$compiler"; then + AC_DEFINE_UNQUOTED(COMPILER, "${BINPREFIX}ccom", + [Define path to alternate compiler]) +fi + +case $wchar_type in +USHORT) wchar_size=2 ;; +UNSIGNED|INT) wchar_size=4 ;; +*) AC_MSG_ERROR([Unknown wchar_t '$wchar_type'.]) ;; +esac + +AC_DEFINE_UNQUOTED(WCHAR_TYPE, $wchar_type, [Type to use for wide characters]) +AC_DEFINE_UNQUOTED(WCHAR_SIZE, $wchar_size, [Size of wide character type in chars]) + +# check for additional compiler flags +AC_PROG_CC +DESIRED_FLAGS="-Wall -Wmissing-prototypes -Wstrict-prototypes -Wshadow -Wsign-compare -Wtruncate" +for flag in $DESIRED_FLAGS +do + AC_MSG_CHECKING([whether $CC accepts $flag]) + AC_LANG_CONFTEST([int main() { return 0; }]) + $CC $CFLAGS $flag -c conftest.c > /dev/null 2> /dev/null + if test $? = 0 ; then + ADD_CFLAGS="$ADD_CFLAGS $flag" + AC_MSG_RESULT([yes]); + else + AC_MSG_RESULT([no]); + fi + rm -f conftest.o +done + +# setup for cross-compiling mkext +AC_MSG_CHECKING([for a C compiler for mkext]) +if test $cross_compiling = yes; then + AC_MSG_RESULT([cross compiling]) + AC_CHECK_PROGS(CC_FOR_BUILD, [pcc gcc cc]) +else + AC_MSG_RESULT([not cross compiling]) + CC_FOR_BUILD=${CC-cc} + AC_SUBST(CC_FOR_BUILD) +fi + +AC_CACHE_CHECK([for C99 printf size specifiers], ac_have_c99_format, [ + AC_RUN_IFELSE([ + AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT], [[ + char buf[64]; + if (sprintf(buf, "%lld%hhd%jd%zd%td", (long long int)1, (char)2, (intmax_t)3, (size_t)4, (ptrdiff_t)5) != 5) + exit(1); + else if (strcmp(buf, "12345")) + exit(2); + ]])], + [ ac_have_c99_format=yes ], + [ ac_have_c99_format=no ], + [ ac_have_c99_format=yes ]) +]) +if test $ac_have_c99_format = yes; then + AC_DEFINE([HAVE_C99_FORMAT], 1, + [Define to 1 if printf supports C99 size specifiers]) +fi + +AC_CACHE_CHECK([for C99 variadic macro support], ac_have_variadic, [ + AC_COMPILE_IFELSE([ + #define macro(...) func(__VA_ARGS__) + int func(int a, ...); + int test() { return macro(1, 2, 3); } + ], [ ac_have_variadic=yes ], [ ac_have_variadic=no ])]) +if test $ac_have_variadic = yes ; then + AC_DEFINE([HAVE_CPP_VARARG_MACRO_GCC], 1, + [Define to 1 if your compiler supports C99 variadic macros]) +fi + +# Byteorder of host +AC_C_BIGENDIAN([AC_DEFINE(HOST_BIG_ENDIAN,[],[Define if host is BIG endian])], + [AC_DEFINE(HOST_LITTLE_ENDIAN,[],[Define if host is LITTLE endian])], + [],[]) + + +# Checks for programs. +AC_PROG_MAKE_SET +AC_PROG_INSTALL +AC_PROG_YACC +AC_CHECK_PROG(strip,strip,yes,no) + +AC_PROG_LEX +if test "$LEX" = flex ; then + AC_DEFINE_UNQUOTED(ISFLEX, 1, [lex is flex]) +fi + +# Checks for libraries. + +# Checks for header files. +# AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h]) +AC_CHECK_HEADERS([string.h malloc.h libgen.h]) +AC_HEADER_SYS_WAIT + +# Checks for library functions. +## AC_FUNC_STRTOD +# AC_FUNC_VPRINTF +# AC_CHECK_FUNCS([memset strchr strdup strrchr strtol]) +AC_CHECK_FUNCS([strtold vsnprintf snprintf mkstemp strlcat strlcpy basename getopt ffs vfork]) + +AC_EXEEXT + +AC_SUBST(targos) +AC_SUBST(targosver) +AC_SUBST(targmach) +AC_SUBST(prefix) +AC_SUBST(exec_prefix) +AC_SUBST(libexecdir) +AC_SUBST(includedir) +AC_SUBST(strip) +AC_SUBST(PACKAGE_VERSION) +AC_SUBST(ADD_CFLAGS) +AC_SUBST(ADD_CPPFLAGS) + +pcc_major=`echo $PACKAGE_VERSION | awk -F. '{print $1}'` +pcc_minor=`echo $PACKAGE_VERSION | awk -F. '{print $2}'` +pcc_minorminor=`echo $PACKAGE_VERSION | awk -F. '{print $3}'` +versstr="\"$PACKAGE_STRING `cat $srcdir/DATESTAMP` for $target, $USER@`hostname`\"" + +AC_DEFINE_UNQUOTED(TARGOS, $targos, [Target OS]) +AC_DEFINE_UNQUOTED(TARGOSVER, $targosver, [Target OS version]) +AC_DEFINE_UNQUOTED(PCC_MAJOR, $pcc_major, [Major version no]) +AC_DEFINE_UNQUOTED(PCC_MINOR, $pcc_minor, [Minor version no]) +AC_DEFINE_UNQUOTED(PCC_MINORMINOR, $pcc_minorminor, [Minor minor version no]) +AC_DEFINE_UNQUOTED(VERSSTR, $versstr, [Version string]) + +AC_CONFIG_FILES([Makefile + cc/Makefile + cc/cc/Makefile + cc/cpp/Makefile + cc/ccom/Makefile + f77/Makefile + f77/f77/Makefile + f77/fcom/Makefile +]) +AC_OUTPUT + +eval "exec_prefix=$exec_prefix" +eval "bindir=$bindir" +eval "libexecdir=$libexecdir" + +echo +echo "Target CPU is .................... ${targmach}" +echo "Target ABI is .................... ${abi}" +echo "Target OS is ..................... ${targos}" +echo "Compiler is called ............... ${BINPREFIX}pcc${EXEEXT}" +echo "Installing compiler into ......... ${bindir}" +echo "Installing pre-processor into .... ${libexecdir}" +echo "Using assembler .................. ${assembler-}" +echo "Using linker ..................... ${linker-}" +echo "Using include path ............... ${altincdir-}" +echo "Using library path ............... ${altlibdir-}" +echo "Has TLS support .................. $tls" +echo "Has GCC compatibility ............ $gcccompat" +echo "Type of wchar_t is ............... ${wchar_type} (${wchar_size} chars)" +echo +echo "Configure finished. Do 'make && make install' to compile and install. +" diff --git a/compilers/pcc/pcc-1.0.0/f77/CVS/Entries b/compilers/pcc/pcc-1.0.0/f77/CVS/Entries new file mode 100644 index 00000000..55fd61e8 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/CVS/Entries @@ -0,0 +1,4 @@ +/Makefile.in/1.3/Fri Jul 18 14:00:38 2008//Tr-1-0-0-RELEASE +D/f77//// +D/fcom//// +D diff --git a/compilers/pcc/pcc-1.0.0/f77/CVS/Repository b/compilers/pcc/pcc-1.0.0/f77/CVS/Repository new file mode 100644 index 00000000..f9730732 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/CVS/Repository @@ -0,0 +1 @@ +pcc/f77 diff --git a/compilers/pcc/pcc-1.0.0/f77/CVS/Root b/compilers/pcc/pcc-1.0.0/f77/CVS/Root new file mode 100644 index 00000000..71e2ccb9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/CVS/Root @@ -0,0 +1 @@ +/cvsroot diff --git a/compilers/pcc/pcc-1.0.0/f77/CVS/Tag b/compilers/pcc/pcc-1.0.0/f77/CVS/Tag new file mode 100644 index 00000000..060fac05 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/CVS/Tag @@ -0,0 +1 @@ +Nr-1-0-0-RELEASE diff --git a/compilers/pcc/pcc-1.0.0/f77/Makefile.in b/compilers/pcc/pcc-1.0.0/f77/Makefile.in new file mode 100644 index 00000000..603cfc46 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/Makefile.in @@ -0,0 +1,36 @@ +# $Id: Makefile.in,v 1.3 2008/07/18 14:00:38 gmcgarry Exp $ +# +# Makefile.in for top-level of pcc. +# + +@SET_MAKE@ +CC=@CC@ +CFLAGS=@CFLAGS@ @ADD_CFLAGS@ +LDFLAGS=@LDFLAGS@ +CPPFLAGS=@CPPFLAGS@ +YACC=@YACC@ +LEX=@LEX@ + +SUBDIR=f77 fcom + +all: ${SUBDIR} + +install: + cd f77 && ${MAKE} install + cd fcom && ${MAKE} install + +clean: + cd f77 && ${MAKE} clean + cd fcom && ${MAKE} clean + +distclean: + cd f77 && ${MAKE} distclean + cd fcom && ${MAKE} distclean + /bin/rm -rf Makefile config.log stamp-h1 config.status \ + configure.lineno config.h autom4te.cache + +${SUBDIR}: nonexistant + cd $@; $(MAKE) all $(MFLAGS) + +nonexistant: + diff --git a/compilers/pcc/pcc-1.0.0/f77/f77/CVS/Entries b/compilers/pcc/pcc-1.0.0/f77/f77/CVS/Entries new file mode 100644 index 00000000..4f1fcc62 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/f77/CVS/Entries @@ -0,0 +1,4 @@ +/Makefile.in/1.8/Fri Dec 19 08:08:48 2008//Tr-1-0-0-RELEASE +/f77.1/1.2/Wed Dec 24 17:40:41 2008//Tr-1-0-0-RELEASE +/f77.c/1.21/Sat Dec 27 00:36:39 2008//Tr-1-0-0-RELEASE +D diff --git a/compilers/pcc/pcc-1.0.0/f77/f77/CVS/Repository b/compilers/pcc/pcc-1.0.0/f77/f77/CVS/Repository new file mode 100644 index 00000000..b1a8d35b --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/f77/CVS/Repository @@ -0,0 +1 @@ +pcc/f77/f77 diff --git a/compilers/pcc/pcc-1.0.0/f77/f77/CVS/Root b/compilers/pcc/pcc-1.0.0/f77/f77/CVS/Root new file mode 100644 index 00000000..71e2ccb9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/f77/CVS/Root @@ -0,0 +1 @@ +/cvsroot diff --git a/compilers/pcc/pcc-1.0.0/f77/f77/CVS/Tag b/compilers/pcc/pcc-1.0.0/f77/f77/CVS/Tag new file mode 100644 index 00000000..060fac05 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/f77/CVS/Tag @@ -0,0 +1 @@ +Nr-1-0-0-RELEASE diff --git a/compilers/pcc/pcc-1.0.0/f77/f77/Makefile.in b/compilers/pcc/pcc-1.0.0/f77/f77/Makefile.in new file mode 100644 index 00000000..f2ab043d --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/f77/Makefile.in @@ -0,0 +1,52 @@ +# $Id: Makefile.in,v 1.8 2008/12/19 08:08:48 ragge Exp $ +# +# Makefile.in for the f77 frontend of pcc. +# +VPATH=@srcdir@ +top_srcdir=@top_srcdir@ +top_builddir=@top_builddir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libexecdir = @libexecdir@ +includedir = @includedir@ +strip = @strip@ +CC = @CC@ +TARGOS = @targos@ +TARGMACH = @targmach@ +F77LIBDIR=-L${prefix}/lib +CFLAGS = @CFLAGS@ @ADD_CFLAGS@ -DLIBEXECDIR=\"${libexecdir}\" -DINCLUDEDIR=\"${includedir}\" +CPPFLAGS = @CPPFLAGS@ -I${top_builddir} -I${top_srcdir}/os/${TARGOS} -I${MDIR} \ + -Dmach_${TARGMACH} -Dos_${TARGOS} -I${FCOMDIR} -DLANG_F77 \ + -DLIBDIR=\"${F77LIBDIR}\" +LIBS = @LIBS@ +LDFLAGS = @LDFLAGS@ +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +OBJS=f77.o +DEST=@BINPREFIX@f77 + +MIPDIR=${top_srcdir}/mip +MDIR=${top_srcdir}/arch/$(TARGMACH) +FCOMDIR=${top_srcdir}/f77/fcom + +all: ${DEST} + +${DEST}: $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@ + +.c.o: + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c $< + +install: + ${INSTALL_PROGRAM} ${DEST} ${bindir} + @if [ ${strip} = yes ]; then \ + strip ${bindir}/${DEST} ; \ + echo strip ${bindir}/${DEST} ; \ + fi + +clean: + /bin/rm -f $(OBJS) ${DEST} + +distclean: clean + /bin/rm -f Makefile diff --git a/compilers/pcc/pcc-1.0.0/f77/f77/f77.1 b/compilers/pcc/pcc-1.0.0/f77/f77/f77.1 new file mode 100644 index 00000000..d947c90a --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/f77/f77.1 @@ -0,0 +1,175 @@ +.\" $Id: f77.1,v 1.2 2008/12/24 17:40:41 sgk Exp $ +.\" +.\" Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" Redistributions of source code and documentation must retain the above +.\" copyright notice, this list of conditions and the following disclaimer. +.\" Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditionsand the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed or owned by Caldera +.\" International, Inc. +.\" Neither the name of Caldera International, Inc. nor the names of other +.\" contributors may be used to endorse or promote products derived from +.\" this software without specific prior written permission. +.\" +.\" USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA +.\" INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +.\" DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE +.\" FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, +.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +.\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.TH F77 1 +.SH NAME +f77 \- Fortran 77 compiler +.SH SYNOPSIS +.B f77 +[ option ] ... file ... +.SH DESCRIPTION +.I F77 +is the UNIX Fortran 77 compiler. +It accepts several types of arguments: +.PP +Arguments whose names end with `.f' are taken to be +Fortran 77 source programs; +they are compiled, and +each object program is left on the file in the current directory +whose name is that of the source with `.o' substituted +for '.f'. +.PP +Arguments whose names end with `.r' or `.e' are taken to be Ratfor or EFL +source programs, respectively; these are first transformed by the +appropriate preprocessor, then compiled by f77. +.PP +In the same way, +arguments whose names end with `.c' or `.s' are taken to be C or assembly source programs +and are compiled or assembled, producing a `.o' file. +.PP +The following options have the same meaning as in +.IR cc (1). +See +.IR ld (1) +for load-time options. +.TP +.B \-c +Suppress loading and produce `.o' files for each source +file. +.TP +.B \-p +Prepare object files for profiling, see +.IR prof (1). +.TP +.SM +.B \-O +Invoke an +object-code optimizer. +.TP +.SM +.B \-S +Compile the named programs, and leave the +assembler-language output on corresponding files suffixed `.s'. +(No `.o' is created.). +.TP +.B \-f +Use a floating point interpreter (for PDP11's that lack +11/70-style floating point). +.TP +.BR \-o " output" +Name the final output file +.I output +instead of `a.out'. +.PP +The following options are peculiar to +.IR f77 . +.TP +.SM +.BR \-onetrip +Compile DO loops that are performed at least once if reached. +(Fortran 77 DO loops are not performed at all if the upper limit is smaller than the lower limit.) +.TP +.BR \-u +Make the default type of a variable `undefined' rather than using the default Fortran rules. +.TP +.BR \-q +Suppress printing of procedure names during compilation. +.TP +.BR \-C +Compile code to check that subscripts are within declared array bounds. +.TP +.BR \-w +Suppress all warning messages. +If the option is `\-w66', only Fortran 66 compatibility warnings are suppressed. +.TP +.BR \-F +Apply EFL and Ratfor preprocessor to relevant files, put the result in the file +with the suffix changed to `.f', but do not compile. +.TP +.BR \-m +Apply the M4 preprocessor to each `.r' or `.e' file before transforming +it with the Ratfor or EFL preprocessor. +.TP +.TP +.BI \-E x +Use the string +.I x +as an EFL option in processing `.e' files. +.TP +.BI \-R x +Use the string +.I x +as a Ratfor option in processing `.r' files. +.PP +Other arguments +are taken +to be either loader option arguments, or F77-compatible +object programs, typically produced by an earlier +run, +or perhaps libraries of F77-compatible routines. +These programs, together with the results of any +compilations specified, are loaded (in the order +given) to produce an executable program with name +`a.out'. +.SH FILES +.nf +.ta \w'/usr/lib/libF77.a 'u +file.[fresc] input file +file.o object file +a.out loaded output +./fort[pid].? temporary +/usr/lib/f77pass1 compiler +/lib/f1 pass 2 +/lib/c2 optional optimizer +/usr/lib/libF77.a intrinsic function library +/usr/lib/libI77.a Fortran I/O library +/lib/libc.a C library, see section 3 +.fi +.SH "SEE ALSO" +S. I. Feldman, +P. J. Weinberger, +.I +A Portable Fortran 77 Compiler +.br +prof(1), cc(1), ld(1) +.SH DIAGNOSTICS +The diagnostics produced by +.I f77 +itself are intended to be +self-explanatory. +Occasional messages may be produced by the loader. +.SH BUGS +The Fortran 66 subset of the language has been +exercised extensively; +the newer features have not. diff --git a/compilers/pcc/pcc-1.0.0/f77/f77/f77.c b/compilers/pcc/pcc-1.0.0/f77/f77/f77.c new file mode 100644 index 00000000..2152d369 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/f77/f77.c @@ -0,0 +1,796 @@ +/* $Id: f77.c,v 1.21 2008/12/27 00:36:39 sgk Exp $ */ +/* + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code and documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditionsand the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +char xxxvers[] = "FORTRAN 77 DRIVER, VERSION 1.11, 28 JULY 1978\n"; + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ccconfig.h" + +typedef FILE *FILEP; +typedef int flag; +#define YES 1 +#define NO 0 + +FILEP diagfile; + +static int pid; +static int sigivalue = 0; +static int sigqvalue = 0; + +#ifndef FCOM +#define FCOM "fcom" +#endif + +#ifndef ASSEMBLER +#define ASSEMBLER "as" +#endif + +#ifndef LINKER +#define LINKER "ld" +#endif + +static char *fcom = LIBEXECDIR "/" FCOM ; +static char *asmname = ASSEMBLER ; +static char *ldname = LINKER ; +static char *startfiles[] = STARTFILES; +static char *endfiles[] = ENDFILES; +static char *dynlinker[] = DYNLINKER; +static char *crt0file = CRT0FILE; +static char *macroname = "m4"; +static char *shellname = "/bin/sh"; +static char *aoutname = "a.out" ; +static char *libdir = LIBDIR ; +static char *liblist[] = F77LIBLIST; + +static char *infname; +static char asmfname[15]; +static char prepfname[15]; + +#define MAXARGS 100 +int ffmax; +static char *ffary[MAXARGS]; +static char eflags[30] = ""; +static char rflags[30] = ""; +static char lflag[3] = "-x"; +static char *eflagp = eflags; +static char *rflagp = rflags; +static char **loadargs; +static char **loadp; +static int oflag; + +static flag loadflag = YES; +static flag saveasmflag = NO; +static flag profileflag = NO; +static flag optimflag = NO; +static flag debugflag = NO; +static flag verbose = NO; +static flag fortonly = NO; +static flag macroflag = NO; + +static char *setdoto(char *), *lastchar(char *), *lastfield(char *); +static void intrupt(int); +static void enbint(void (*)(int)); +static void crfnames(void); +static void fatal1(char *, ...); +static void done(int), texec(char *, char **); +static char *copyn(int, char *); +static int dotchar(char *), unreadable(char *), sys(char *), dofort(char *); +static int nodup(char *); +static int await(int); +static void rmf(char *), doload(char *[], char *[]), doasm(char *); +static int callsys(char *, char **); +static void errorx(char *, ...); + +static void +addarg(char **ary, int *num, char *arg) +{ + ary[(*num)++] = arg; + if ((*num) == MAXARGS) { + fprintf(stderr, "argument array too small\n"); + exit(1); + } +} + +int +main(int argc, char **argv) +{ + int i, c, status; + char *s; + char fortfile[20], *t; + char buff[100]; + + diagfile = stderr; + + sigivalue = (int) signal(SIGINT, SIG_IGN) & 01; + sigqvalue = (int) signal(SIGQUIT, SIG_IGN) & 01; + enbint(intrupt); + + pid = getpid(); + crfnames(); + + loadargs = (char **)calloc(1, (argc + 20) * sizeof(*loadargs)); + if (!loadargs) + fatal1("out of memory"); + loadp = loadargs; + + --argc; + ++argv; + + while(argc>0 && argv[0][0]=='-' && argv[0][1]!='\0') { + for(s = argv[0]+1 ; *s ; ++s) + switch(*s) { + case 'T': /* use special passes */ + switch(*++s) { + case '1': + fcom = s+1; goto endfor; + case 'a': + asmname = s+1; goto endfor; + case 'l': + ldname = s+1; goto endfor; + case 'm': + macroname = s+1; goto endfor; + default: + fatal1("bad option -T%c", *s); + } + break; + + case 'w': /* F66 warn or no warn */ + addarg(ffary, &ffmax, s-1); + break; + + case 'q': + /* + * Suppress printing of procedure names during + * compilation. + */ + addarg(ffary, &ffmax, s-1); + break; + + copyfflag: + case 'u': + case 'U': + case 'M': + case '1': + case 'C': + addarg(ffary, &ffmax, s-1); + break; + + case 'O': + optimflag = YES; + addarg(ffary, &ffmax, s-1); + break; + + case 'm': + if(s[1] == '4') + ++s; + macroflag = YES; + break; + + case 'S': + saveasmflag = YES; + + case 'c': + loadflag = NO; + break; + + case 'v': + verbose = YES; + break; + + case 'd': + debugflag = YES; + goto copyfflag; + + case 'p': + profileflag = YES; + goto copyfflag; + + case 'o': + if(!strcmp(s, "onetrip")) { + addarg(ffary, &ffmax, s-1); + goto endfor; + } + oflag = 1; + aoutname = *++argv; + --argc; + break; + + case 'F': + fortonly = YES; + loadflag = NO; + break; + + case 'I': + if(s[1]=='2' || s[1]=='4' || s[1]=='s') + goto copyfflag; + fprintf(diagfile, "invalid flag -I%c\n", s[1]); + done(1); + + case 'l': /* letter ell--library */ + s[-1] = '-'; + *loadp++ = s-1; + goto endfor; + + case 'E': /* EFL flag argument */ + while(( *eflagp++ = *++s)) + ; + *eflagp++ = ' '; + goto endfor; + case 'R': + while(( *rflagp++ = *++s )) + ; + *rflagp++ = ' '; + goto endfor; + default: + lflag[1] = *s; + *loadp++ = copyn(strlen(lflag), lflag); + break; + } +endfor: + --argc; + ++argv; + } + + if (verbose) + fprintf(stderr, xxxvers); + + if (argc == 0) + errorx("No input files"); + +#ifdef mach_pdp11 + if(nofloating) + *loadp++ = (profileflag ? NOFLPROF : NOFLFOOT); + else +#endif + + for(i = 0 ; i%s", macroname, infname, prepfname); + if(sys(buff)) { + rmf(prepfname); + break; + } + infname = prepfname; + } + + if(c == 'e') + sprintf(buff, "efl %s %s >%s", eflags, infname, fortfile); + else + sprintf(buff, "ratfor %s %s >%s", rflags, infname, fortfile); + status = sys(buff); + if(macroflag) + rmf(infname); + if(status) { + loadflag = NO; + rmf(fortfile); + break; + } + + if( ! fortonly ) { + infname = argv[i] = lastfield(argv[i]); + *lastchar(infname) = 'f'; + + if( dofort(argv[i]) ) + loadflag = NO; + else { + if( nodup(t = setdoto(argv[i])) ) + *loadp++ = t; + rmf(fortfile); + } + } + break; + + case 'f': /* Fortran file */ + case 'F': + if( unreadable(argv[i]) ) + break; + if( dofort(argv[i]) ) + loadflag = NO; + else if( nodup(t=setdoto(argv[i])) ) + *loadp++ = t; + break; + + case 'c': /* C file */ + case 's': /* Assembler file */ + if( unreadable(argv[i]) ) + break; + fprintf(diagfile, "%s:\n", argv[i]); + sprintf(buff, "cc -c %s", argv[i] ); + if( sys(buff) ) + loadflag = NO; + else + if( nodup(t = setdoto(argv[i])) ) + *loadp++ = t; + break; + + case 'o': + if( nodup(argv[i]) ) + *loadp++ = argv[i]; + break; + + default: + if( ! strcmp(argv[i], "-o") ) + aoutname = argv[++i]; + else + *loadp++ = argv[i]; + break; + } + + if(loadflag) + doload(loadargs, loadp); + done(0); + return 0; +} + +#define ADD(x) addarg(params, &nparms, (x)) + +static int +dofort(char *s) +{ + int nparms, i; + char *params[MAXARGS]; + + nparms = 0; + ADD(FCOM); + for (i = 0; i < ffmax; i++) + ADD(ffary[i]); + ADD(s); + ADD(asmfname); + ADD(NULL); + + infname = s; + if (callsys(fcom, params)) + errorx("Error. No assembly."); + doasm(s); + + if (saveasmflag == NO) + rmf(asmfname); + return(0); +} + + +static void +doasm(char *s) +{ + char *obj; + char *params[MAXARGS]; + int nparms; + + if (oflag && loadflag == NO) + obj = aoutname; + else + obj = setdoto(s); + + nparms = 0; + ADD(asmname); + ADD("-o"); + ADD(obj); + ADD(asmfname); + ADD(NULL); + + if (callsys(asmname, params)) + fatal1("assembler error"); + if(verbose) + fprintf(diagfile, "\n"); +} + + +static void +doload(char *v0[], char *v[]) +{ + int nparms, i; + char *params[MAXARGS]; + char **p; + + nparms = 0; + ADD(ldname); + ADD("-X"); + ADD("-d"); + for (i = 0; dynlinker[i]; i++) + ADD(dynlinker[i]); + ADD("-o"); + ADD(aoutname); + ADD(crt0file); + for (i = 0; startfiles[i]; i++) + ADD(startfiles[i]); + *v = NULL; + for(p = v0; *p ; p++) + ADD(*p); + if (libdir) + ADD(libdir); + for(p = liblist ; *p ; p++) + ADD(*p); + for (i = 0; endfiles[i]; i++) + ADD(endfiles[i]); + ADD(NULL); + + if (callsys(ldname, params)) + fatal1("couldn't load %s", ldname); + + if(verbose) + fprintf(diagfile, "\n"); +} + +/* Process control and Shell-simulating routines */ + +/* + * Execute f[] with parameter array v[]. + * Copied from cc. + */ +static int +callsys(char f[], char *v[]) +{ + int t, status = 0; + pid_t p; + char *s; + + if (debugflag || verbose) { + fprintf(stderr, "%s ", f); + for (t = 1; v[t]; t++) + fprintf(stderr, "%s ", v[t]); + fprintf(stderr, "\n"); + } + + if ((p = fork()) == 0) { +#ifdef notyet + if (Bflag) { + size_t len = strlen(Bflag) + 8; + char *a = malloc(len); + if (a == NULL) { + error("callsys: malloc failed"); + exit(1); + } + if ((s = strrchr(f, '/'))) { + strlcpy(a, Bflag, len); + strlcat(a, s, len); + execv(a, v); + } + } +#endif + execvp(f, v); + if ((s = strrchr(f, '/'))) + execvp(s+1, v); + fprintf(stderr, "Can't find %s\n", f); + _exit(100); + } else { + if (p == -1) { + printf("Try again\n"); + return(100); + } + } + while (waitpid(p, &status, 0) == -1 && errno == EINTR) + ; + if (WIFEXITED(status)) + return (WEXITSTATUS(status)); + if (WIFSIGNALED(status)) + done(1); + fatal1("Fatal error in %s", f); + return 0; /* XXX */ +} + + +static int +sys(char *str) +{ + char *s, *t; + char *argv[100], path[100]; + char *inname, *outname; + int append = 0; + int wait_pid; + int argc; + + + if(debugflag) + fprintf(diagfile, "%s\n", str); + inname = NULL; + outname = NULL; + argv[0] = shellname; + argc = 1; + + t = str; + while( isspace((int)*t) ) + ++t; + while(*t) { + if(*t == '<') + inname = t+1; + else if(*t == '>') { + if(t[1] == '>') { + append = YES; + outname = t+2; + } else { + append = NO; + outname = t+1; + } + } else + argv[argc++] = t; + while( !isspace((int)*t) && *t!='\0' ) + ++t; + if(*t) { + *t++ = '\0'; + while( isspace((int)*t) ) + ++t; + } + } + + if(argc == 1) /* no command */ + return(-1); + argv[argc] = 0; + + s = path; + t = "/usr/bin/"; + while(*t) + *s++ = *t++; + for(t = argv[1] ; (*s++ = *t++) ; ) + ; + if((wait_pid = fork()) == 0) { + if(inname) + freopen(inname, "r", stdin); + if(outname) + freopen(outname, (append ? "a" : "w"), stdout); + enbint(SIG_DFL); + + texec(path+9, argv); /* command */ + texec(path+4, argv); /* /bin/command */ + texec(path , argv); /* /usr/bin/command */ + + fatal1("Cannot load %s",path+9); + } + + return( await(wait_pid) ); +} + +/* modified version from the Shell */ +static void +texec(char *f, char **av) +{ + + execv(f, av+1); + + if (errno==ENOEXEC) { + av[1] = f; + execv(shellname, av); + fatal1("No shell!"); + } + if (errno==ENOMEM) + fatal1("%s: too large", f); +} + +/* + * Cleanup and exit with value k. + */ +static void +done(int k) +{ + static int recurs = NO; + + if(recurs == NO) { + recurs = YES; + if (saveasmflag == NO) + rmf(asmfname); + } + exit(k); +} + + +static void +enbint(void (*k)(int)) +{ +if(sigivalue == 0) + signal(SIGINT,k); +if(sigqvalue == 0) + signal(SIGQUIT,k); +} + + + +static void +intrupt(int a) +{ +done(2); +} + + +static int +await(int wait_pid) +{ +int w, status; + +enbint(SIG_IGN); +while ( (w = wait(&status)) != wait_pid) + if(w == -1) + fatal1("bad wait code"); +enbint(intrupt); +if(status & 0377) + { + if(status != SIGINT) + fprintf(diagfile, "Termination code %d", status); + done(3); + } +return(status>>8); +} + +/* File Name and File Manipulation Routines */ + +static int +unreadable(char *s) +{ + FILE *fp; + + if((fp = fopen(s, "r"))) { + fclose(fp); + return(NO); + } else { + fprintf(diagfile, "Error: Cannot read file %s\n", s); + loadflag = NO; + return(YES); + } +} + + +static void +crfnames(void) +{ + sprintf(asmfname, "fort%d.%s", pid, "s"); + sprintf(prepfname, "fort%d.%s", pid, "p"); +} + + + +static void +rmf(char *fn) +{ +if(!debugflag && fn!=NULL && *fn!='\0') + unlink(fn); +} + + +static int +dotchar(char *s) +{ +for( ; *s ; ++s) + if(s[0]=='.' && s[1]!='\0' && s[2]=='\0') + return( s[1] ); +return(NO); +} + + +static char * +lastfield(char *s) +{ +char *t; +for(t = s; *s ; ++s) + if(*s == '/') + t = s+1; +return(t); +} + + +static char * +lastchar(char *s) +{ +while(*s) + ++s; +return(s-1); +} + + +static char * +setdoto(char *s) +{ +*lastchar(s) = 'o'; +return( lastfield(s) ); +} + + +static char * +copyn(int n, char *s) +{ + char *p, *q; + + p = q = (char *)calloc(1, (unsigned) n + 1); + if (!p) + fatal1("out of memory"); + + while(n-- > 0) + *q++ = *s++; + return (p); +} + + +static int +nodup(char *s) +{ +char **p; + +for(p = loadargs ; p < loadp ; ++p) + if( !strcmp(*p, s) ) + return(NO); + +return(YES); +} + + +static void +errorx(char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(diagfile, fmt, ap); + fprintf(diagfile, "\n"); + va_end(ap); + + if (debugflag) + abort(); + done(1); +} + + +static void +fatal1(char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + fprintf(diagfile, "Compiler error in file %s: ", infname); + vfprintf(diagfile, fmt, ap); + fprintf(diagfile, "\n"); + va_end(ap); + + if (debugflag) + abort(); + done(1); +} diff --git a/compilers/pcc/pcc-1.0.0/f77/fcom/CVS/Entries b/compilers/pcc/pcc-1.0.0/f77/fcom/CVS/Entries new file mode 100644 index 00000000..c6292818 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/fcom/CVS/Entries @@ -0,0 +1,26 @@ +/Makefile.in/1.13/Fri Dec 19 08:08:48 2008//Tr-1-0-0-RELEASE +/data.c/1.15/Sun May 11 15:28:03 2008//Tr-1-0-0-RELEASE +/defines.h/1.15/Sat May 10 07:53:41 2008//Tr-1-0-0-RELEASE +/defs.h/1.22/Wed Dec 24 17:40:41 2008//Tr-1-0-0-RELEASE +/equiv.c/1.11/Sun May 11 15:28:03 2008//Tr-1-0-0-RELEASE +/error.c/1.8/Sat May 10 07:53:41 2008//Tr-1-0-0-RELEASE +/exec.c/1.14/Sun May 11 15:28:03 2008//Tr-1-0-0-RELEASE +/expr.c/1.20/Sun May 11 15:28:03 2008//Tr-1-0-0-RELEASE +/ftypes.h/1.5/Fri Dec 19 08:08:48 2008//Tr-1-0-0-RELEASE +/gram.dcl/1.7/Sat May 10 08:44:17 2008//Tr-1-0-0-RELEASE +/gram.exec/1.4/Sat May 10 08:39:27 2008//Tr-1-0-0-RELEASE +/gram.expr/1.4/Sun May 4 09:51:57 2008//Tr-1-0-0-RELEASE +/gram.head/1.9/Sat May 10 07:53:41 2008//Tr-1-0-0-RELEASE +/gram.io/1.1/Sun Apr 17 13:54:38 2005//Tr-1-0-0-RELEASE +/init.c/1.16/Wed Dec 24 17:40:41 2008//Tr-1-0-0-RELEASE +/intr.c/1.13/Sun May 11 15:28:03 2008//Tr-1-0-0-RELEASE +/io.c/1.15/Fri Dec 19 08:08:48 2008//Tr-1-0-0-RELEASE +/lex.c/1.12/Sun May 11 15:28:03 2008//Tr-1-0-0-RELEASE +/main.c/1.14/Mon Feb 9 15:59:48 2009//Tr-1-0-0-RELEASE +/misc.c/1.17/Wed Feb 11 15:58:55 2009//Tr-1-0-0-RELEASE +/proc.c/1.14/Wed Dec 24 17:40:41 2008//Tr-1-0-0-RELEASE +/put.c/1.17/Sun May 11 15:28:03 2008//Tr-1-0-0-RELEASE +/putscj.c/1.18/Fri Dec 19 08:08:48 2008//Tr-1-0-0-RELEASE +/scjdefs.h/1.9/Sun Mar 23 09:17:44 2008//Tr-1-0-0-RELEASE +/tokens/1.2/Wed Mar 5 18:50:33 2008//Tr-1-0-0-RELEASE +D diff --git a/compilers/pcc/pcc-1.0.0/f77/fcom/CVS/Repository b/compilers/pcc/pcc-1.0.0/f77/fcom/CVS/Repository new file mode 100644 index 00000000..8e31856b --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/fcom/CVS/Repository @@ -0,0 +1 @@ +pcc/f77/fcom diff --git a/compilers/pcc/pcc-1.0.0/f77/fcom/CVS/Root b/compilers/pcc/pcc-1.0.0/f77/fcom/CVS/Root new file mode 100644 index 00000000..71e2ccb9 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/fcom/CVS/Root @@ -0,0 +1 @@ +/cvsroot diff --git a/compilers/pcc/pcc-1.0.0/f77/fcom/CVS/Tag b/compilers/pcc/pcc-1.0.0/f77/fcom/CVS/Tag new file mode 100644 index 00000000..060fac05 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/fcom/CVS/Tag @@ -0,0 +1 @@ +Nr-1-0-0-RELEASE diff --git a/compilers/pcc/pcc-1.0.0/f77/fcom/Makefile.in b/compilers/pcc/pcc-1.0.0/f77/fcom/Makefile.in new file mode 100644 index 00000000..71871eda --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/fcom/Makefile.in @@ -0,0 +1,121 @@ +# $Id: Makefile.in,v 1.13 2008/12/19 08:08:48 ragge Exp $ +# +# Makefile for the Fortran 77 command +# Running on the @targmach@ +# Generating code for the @targmach@ +# Using the Johnson C compiler's second pass (binary version) +VPATH=@srcdir@ +srcdir=@srcdir@ +top_srcdir=@top_srcdir@ +builddir=@builddir@ +top_builddir=@top_builddir@ +XFL=-DPCC_DEBUG -Wall -Wmissing-prototypes -Wstrict-prototypes -Werror \ + -Werror -Wshadow -Wsign-compare + +CC = @CC@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ @ADD_CFLAGS@ +CPPFLAGS = @CPPFLAGS@ ${XFL} -DFCOM -DLANG_F77 -Dos_${TARGOS} \ + -I${srcdir} -I${builddir} -I${top_builddir} \ + -I${MIPDIR} -I${MDIR} -Dmach_${TARGMACH} -I${top_srcdir}/os/${TARGOS} +LIBS = @LIBS@ +LDFLAGS = @LDFLAGS@ +TARGOS = @targos@ +TARGMACH = @targmach@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +libexecdir = @libexecdir@ +datarootdir = @datarootdir@ +mandir = @mandir@ +strip = @strip@ +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +YFLAGS = -d + +MDIR=$(top_srcdir)/arch/$(TARGMACH) +MIPDIR=$(top_srcdir)/mip + +DEST=@BINPREFIX@fcom + +OBJS1 = main.o init.o proc.o gram.o lex.o \ + equiv.o data.o expr.o exec.o intr.o io.o misc.o error.o\ + put.o putscj.o flocal.o + +OBJS2=match.o reader.o optim2.o regs.o local2.o order.o table.o + +OBJS=$(OBJS1) $(OBJS2) common.o external.o + +all: ${DEST} + +${DEST}: $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@ + +gram.c: gram.head gram.dcl gram.expr gram.exec gram.io tokdefs + ( sed gram.in + $(YACC) $(YFLAGS) gram.in + mv y.tab.c gram.c + mv y.tab.h gram.h + rm gram.in + +tokdefs: tokens + grep -n . tokdefs + +lex.o : tokdefs +driver.o $(OBJS) : defs.h defines.h ftypes.h + +clean: + /bin/rm -f $(OBJS) ${DEST} gram.in gram.[ch] tokdefs \ + mkext external.[ch] + +distclean: clean + /bin/rm -f Makefile + +install: + ${INSTALL_PROGRAM} ${DEST} ${libexecdir} + @if [ ${strip} = yes ]; then \ + strip ${libexecdir}/${DEST} ; \ + echo strip ${libexecdir}/${DEST} ; \ + fi + +.c.o : + $(CC) -c $(CFLAGS) $(CPPFLAGS) $*.c + +flocal.o: $(MDIR)/flocal.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $(MDIR)/flocal.c + +local2.o: $(MDIR)/local2.c + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MDIR)/local2.c + +order.o: $(MDIR)/order.c + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MDIR)/order.c + +table.o: $(MDIR)/table.c + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MDIR)/table.c + +match.o: $(MIPDIR)/match.c + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/match.c + +reader.o: $(MIPDIR)/reader.c + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/reader.c + +optim2.o: $(MIPDIR)/optim2.c + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/optim2.c + +regs.o: $(MIPDIR)/regs.c + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/regs.c + +compat.o: $(MIPDIR)/compat.c + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/compat.c + +common.o: $(MIPDIR)/common.c + $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(MIPDIR)/common.c + +external.h external.c: ${MIPDIR}/mkext.c $(MDIR)/table.c + $(CC_FOR_BUILD) $(DEFS) $(CPPFLAGS) $(CFLAGS) -DMKEXT -o mkext \ + ${MIPDIR}/mkext.c $(MDIR)/table.c ${MIPDIR}/common.c + ./mkext + -rm -f mkext.o table.o common.o + +$(OBJS): external.h + diff --git a/compilers/pcc/pcc-1.0.0/f77/fcom/data.c b/compilers/pcc/pcc-1.0.0/f77/fcom/data.c new file mode 100644 index 00000000..6313b5dd --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/fcom/data.c @@ -0,0 +1,358 @@ +/* $Id: data.c,v 1.15 2008/05/11 15:28:03 ragge Exp $ */ +/* + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code and documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditionsand the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "defines.h" +#include "defs.h" + +#if 1 /* RAGGE */ +extern FILE *initfile; +#endif + +/* ROUTINES CALLED DURING DATA STATEMENT PROCESSING */ +LOCAL void setdata(struct bigblock *, struct bigblock *, ftnint, ftnint); + +static char datafmt[] = "%s\t%05ld\t%05ld\t%d" ; + +/* another initializer, called from parser */ +void +dataval(repp, valp) +register struct bigblock *repp, *valp; +{ +int i, nrep; +ftnint elen, vlen; +register struct bigblock *p; + +if(repp == NULL) + nrep = 1; +else if (ISICON(repp) && repp->b_const.fconst.ci >= 0) + nrep = repp->b_const.fconst.ci; +else + { + err("invalid repetition count in DATA statement"); + frexpr(repp); + goto ret; + } +frexpr(repp); + +if( ! ISCONST(valp) ) + { + err("non-constant initializer"); + goto ret; + } + +if(toomanyinit) goto ret; +for(i = 0 ; i < nrep ; ++i) + { + p = nextdata(&elen, &vlen); + if(p == NULL) + { + err("too many initializers"); + toomanyinit = YES; + goto ret; + } + setdata(p, valp, elen, vlen); + frexpr(p); + } + +ret: + frexpr(valp); +} + + +struct bigblock *nextdata(elenp, vlenp) +ftnint *elenp, *vlenp; +{ +register struct bigblock *ip; +struct bigblock *pp; +register struct bigblock *np; +register chainp rp; +bigptr p; +bigptr neltp; +register bigptr q; +int skip; +ftnint off; + +while(curdtp) + { + p = curdtp->chain.datap; + if(p->tag == TIMPLDO) + { + ip = p; + if(ip->b_impldo.implb==NULL || ip->b_impldo.impub==NULL || ip->b_impldo.varnp==NULL) + fatal1("bad impldoblock 0%o", ip); + if(ip->isactive) + ip->b_impldo.varvp->b_const.fconst.ci += ip->b_impldo.impdiff; + else + { + q = fixtype(cpexpr(ip->b_impldo.implb)); + if( ! ISICON(q) ) + goto doerr; + ip->b_impldo.varvp = q; + + if(ip->b_impldo.impstep) + { + q = fixtype(cpexpr(ip->b_impldo.impstep)); + if( ! ISICON(q) ) + goto doerr; + ip->b_impldo.impdiff = q->b_const.fconst.ci; + frexpr(q); + } + else + ip->b_impldo.impdiff = 1; + + q = fixtype(cpexpr(ip->b_impldo.impub)); + if(! ISICON(q)) + goto doerr; + ip->b_impldo.implim = q->b_const.fconst.ci; + frexpr(q); + + ip->isactive = YES; + rp = ALLOC(rplblock); + rp->rplblock.nextp = rpllist; + rpllist = rp; + rp->rplblock.rplnp = ip->b_impldo.varnp; + rp->rplblock.rplvp = ip->b_impldo.varvp; + rp->rplblock.rpltag = TCONST; + } + + if( (ip->b_impldo.impdiff>0 && + (ip->b_impldo.varvp->b_const.fconst.ci <= ip->b_impldo.implim)) + || (ip->b_impldo.impdiff<0 && + (ip->b_impldo.varvp->b_const.fconst.ci >= ip->b_impldo.implim))) + { /* start new loop */ + curdtp = ip->b_impldo.datalist; + goto next; + } + + /* clean up loop */ + + popstack(&rpllist); + + frexpr(ip->b_impldo.varvp); + ip->isactive = NO; + curdtp = curdtp->chain.nextp; + goto next; + } + + pp = p; + np = pp->b_prim.namep; + skip = YES; + + if(p->b_prim.argsp==NULL && np->b_name.vdim!=NULL) + { /* array initialization */ + q = mkaddr(np); + off = typesize[np->vtype] * curdtelt; + if(np->vtype == TYCHAR) + off *= np->vleng->b_const.fconst.ci; + q->b_addr.memoffset = mkexpr(OPPLUS, q->b_addr.memoffset, mkintcon(off) ); + if( (neltp = np->b_name.vdim->nelt) && ISCONST(neltp)) + { + if(++curdtelt < neltp->b_const.fconst.ci) + skip = NO; + } + else + err("attempt to initialize adjustable array"); + } + else + q = mklhs( cpexpr(pp) ); + if(skip) + { + curdtp = curdtp->chain.nextp; + curdtelt = 0; + } + if(q->vtype == TYCHAR) + if(ISICON(q->vleng)) + *elenp = q->vleng->b_const.fconst.ci; + else { + err("initialization of string of nonconstant length"); + continue; + } + else *elenp = typesize[q->vtype]; + + if(np->vstg == STGCOMMON) + *vlenp = extsymtab[np->b_name.vardesc.varno].maxleng; + else if(np->vstg == STGEQUIV) + *vlenp = eqvclass[np->b_name.vardesc.varno].eqvleng; + else { + *vlenp = (np->vtype==TYCHAR ? + np->vleng->b_const.fconst.ci : typesize[np->vtype]); + if(np->b_name.vdim) + *vlenp *= np->b_name.vdim->nelt->b_const.fconst.ci; + } + return(q); + +doerr: + err("nonconstant implied DO parameter"); + frexpr(q); + curdtp = curdtp->chain.nextp; + +next: curdtelt = 0; + } + +return(NULL); +} + + + + + + +LOCAL void setdata(varp, valp, elen, vlen) +struct bigblock *varp; +ftnint elen, vlen; +struct bigblock *valp; +{ +union constant con; +int i, k; +int stg, type, valtype; +ftnint offset; +register char *s, *t; +static char varname[XL+2]; + +/* output form of name is padded with blanks and preceded + with a storage class digit +*/ + +stg = varp->vstg; +varname[0] = (stg==STGCOMMON ? '2' : (stg==STGEQUIV ? '1' : '0') ); +s = memname(stg, varp->b_addr.memno); +for(t = varname+1 ; *s ; ) + *t++ = *s++; +while(t < varname+XL+1) + *t++ = ' '; +varname[XL+1] = '\0'; + +offset = varp->b_addr.memoffset->b_const.fconst.ci; +type = varp->vtype; +valtype = valp->vtype; +if(type!=TYCHAR && valtype==TYCHAR) + { + if(! ftn66flag) + warn("non-character datum initialized with character string"); + varp->vleng = MKICON(typesize[type]); + varp->vtype = type = TYCHAR; + } +else if( (type==TYCHAR && valtype!=TYCHAR) || + (cktype(OPASSIGN,type,valtype) == TYERROR) ) + { + err("incompatible types in initialization"); + return; + } +if(type != TYCHAR) { + if(valtype == TYUNKNOWN) + con.ci = valp->b_const.fconst.ci; + else consconv(type, &con, valtype, &valp->b_const.fconst); +} + +k = 1; +switch(type) + { + case TYLOGICAL: + type = tylogical; + case TYSHORT: + case TYLONG: + fprintf(initfile, datafmt, varname, offset, vlen, type); + prconi(initfile, type, con.ci); + break; + + case TYCOMPLEX: + k = 2; + type = TYREAL; + case TYREAL: + goto flpt; + + case TYDCOMPLEX: + k = 2; + type = TYDREAL; + case TYDREAL: + flpt: + + for(i = 0 ; i < k ; ++i) + { + fprintf(initfile, datafmt, varname, offset, vlen, type); + prconr(initfile, type, con.cd[i]); + offset += typesize[type]; + } + break; + + case TYCHAR: + k = valp->vleng->b_const.fconst.ci; + if(elen < k) + k = elen; + + for(i = 0 ; i < k ; ++i) + { + fprintf(initfile, datafmt, varname, offset++, vlen, TYCHAR); + fprintf(initfile, "\t%d\n", valp->b_const.fconst.ccp[i]); + } + k = elen - valp->vleng->b_const.fconst.ci; + while( k-- > 0) + { + fprintf(initfile, datafmt, varname, offset++, vlen, TYCHAR); + fprintf(initfile, "\t%d\n", ' '); + } + break; + + default: + fatal1("setdata: impossible type %d", type); + } + +} + + +void +frdata(p0) +chainp p0; +{ +register chainp p; +register bigptr q; + +for(p = p0 ; p ; p = p->chain.nextp) + { + q = p->chain.datap; + if(q->tag == TIMPLDO) + { + if(q->isbusy) + return; /* circular chain completed */ + q->isbusy = YES; + frdata(q->b_impldo.datalist); + ckfree(q); + } + else + frexpr(q); + } + +frchain( &p0); +} diff --git a/compilers/pcc/pcc-1.0.0/f77/fcom/defines.h b/compilers/pcc/pcc-1.0.0/f77/fcom/defines.h new file mode 100644 index 00000000..4ea3a65d --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/fcom/defines.h @@ -0,0 +1,267 @@ +/* $Id: defines.h,v 1.15 2008/05/10 07:53:41 ragge Exp $ */ +/* + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code and documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditionsand the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include + +#ifdef FCOM +#include "pass2.h" +#endif +#include "ftypes.h" + +#define INTERDATA 2 +#define GCOS 3 +#define PDP11 4 +#define IBM 5 +#define CMACH 6 +#define VAX 7 + +#define DMR 2 +#define SCJ 3 + +#define BINARY 2 +#define ASCII 3 + +#define PREFIX 2 +#define POSTFIX 3 + +#define M(x) (1<tag==TCONST && ISINT(z->vtype)) +#define ISCHAR(z) (z->vtype==TYCHAR) +#define ISINT(z) ONEOF(z, MSKINT) +#define ISCONST(z) (z->tag==TCONST) +#define ISERROR(z) (z->tag==TERROR) +#define ISPLUSOP(z) (z->tag==TEXPR && z->b_expr.opcode==OPPLUS) +#define ISSTAROP(z) (z->tag==TEXPR && z->b_expr.opcode==OPSTAR) +#define ISONE(z) (ISICON(z) && z->b_const.fconst.ci==1) +/* #define INT(z) ONEOF(z, MSKINT|MSKCHAR) */ +#define MKICON(z) mkintcon( (ftnint)(z) ) +#define CHCON(z) mkstrcon(strlen(z), z) + +/* round a up to a multiple of b */ +#define roundup(a,b) ( b * ( (a+b-1)/b) ) + +/* prototypes for cpu-specific functions */ +void prchars(int *); + diff --git a/compilers/pcc/pcc-1.0.0/f77/fcom/defs.h b/compilers/pcc/pcc-1.0.0/f77/fcom/defs.h new file mode 100644 index 00000000..aa575a89 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/fcom/defs.h @@ -0,0 +1,562 @@ +/* $Id: defs.h,v 1.22 2008/12/24 17:40:41 sgk Exp $ */ +/* + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code and documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditionsand the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include + +#define VL 6 +#define XL 8 + +#define MAXINCLUDES 10 +#define MAXLITERALS 20 +#define MAXCTL 20 +#define MAXHASH 401 +#define MAXSTNO 1000 +#define MAXEXT 200 +#define MAXEQUIV 150 +#define MAXLABLIST 100 + +typedef struct bigblock *bigptr; +typedef union chainedblock *chainp; + +extern FILE *infile; +extern FILE *diagfile; +extern long int headoffset; + +extern char token [ ]; +extern int toklen; +extern int lineno; +extern char *infname; +extern int needkwd; +extern struct labelblock *thislabel; + +extern int mflag, tflag; + +extern flag profileflag; +extern flag optimflag; +extern flag quietflag; +extern flag nowarnflag; +extern flag ftn66flag; +extern flag shiftcase; +extern flag undeftype; +extern flag shortsubs; +extern flag onetripflag; +extern flag checksubs; +extern flag debugflag; +extern int nerr; +extern int nwarn; +extern int ndata; + +extern int parstate; +extern flag headerdone; +extern int blklevel; +extern flag saveall; +extern flag substars; +extern int impltype[ ]; +extern int implleng[ ]; +extern int implstg[ ]; + +extern int tyint; +extern int tylogical; +extern ftnint typesize[]; +extern int typealign[]; +extern int procno; +extern int proctype; +extern char * procname; +extern int rtvlabel[ ]; +extern int fudgelabel; /* to confuse the pdp11 optimizer */ +extern struct bigblock *typeaddr; +extern struct bigblock *retslot; +extern int cxslot; +extern int chslot; +extern int chlgslot; +extern int procclass; +extern ftnint procleng; +extern int nentry; +extern flag multitype; +extern int blklevel; +extern int lastlabno; +extern int lastvarno; +extern int lastargslot; +extern int argloc; +extern ftnint autoleng; +extern ftnint bssleng; +extern int retlabel; +extern int ret0label; +extern int dorange; +extern int regnum[ ]; +extern bigptr regnamep[ ]; +extern int maxregvar; +extern int highregvar; + +extern chainp templist; +extern chainp holdtemps; +extern chainp entries; +extern chainp rpllist; +extern chainp curdtp; +extern ftnint curdtelt; +extern flag toomanyinit; + +extern flag inioctl; +extern int iostmt; +extern struct bigblock *ioblkp; +extern int nioctl; +extern int nequiv; +extern int nintnames; +extern int nextnames; + +struct chain + { + chainp nextp; + bigptr datap; + }; + +extern chainp chains; + +struct ctlframe + { + unsigned ctltype:8; + unsigned dostepsign:8; + int ctlabels[4]; + int dolabel; + struct bigblock *donamep; + bigptr domax; + bigptr dostep; + }; +#define endlabel ctlabels[0] +#define elselabel ctlabels[1] +#define dobodylabel ctlabels[1] +#define doposlabel ctlabels[2] +#define doneglabel ctlabels[3] +extern struct ctlframe ctls[ ]; +extern struct ctlframe *ctlstack; +extern struct ctlframe *lastctl; + +struct extsym + { + char extname[XL]; + unsigned extstg:4; + unsigned extsave:1; + unsigned extinit:1; + chainp extp; + ftnint extleng; + ftnint maxleng; + }; + +extern struct extsym extsymtab[ ]; +extern struct extsym *nextext; +extern struct extsym *lastext; + +struct labelblock + { + int labelno; + unsigned blklevel:8; + unsigned labused:1; + unsigned labinacc:1; + unsigned labdefined:1; + unsigned labtype:2; + ftnint stateno; + }; + +extern struct labelblock labeltab[ ]; +extern struct labelblock *labtabend; +extern struct labelblock *highlabtab; + +struct entrypoint + { + chainp nextp; + struct extsym *entryname; + chainp arglist; + int entrylabel; + int typelabel; + ptr enamep; + }; + +struct primblock + { + struct bigblock *namep; + struct bigblock *argsp; + bigptr fcharp; + bigptr lcharp; + }; + + +struct hashentry + { + int hashval; + struct bigblock *varp; + }; +extern struct hashentry hashtab[ ]; +extern struct hashentry *lasthash; + +struct intrpacked /* bits for intrinsic function description */ + { + unsigned f1:3; + unsigned f2:4; + unsigned f3:7; + }; + +struct nameblock + { + char varname[VL]; + unsigned vdovar:1; + unsigned vdcldone:1; + unsigned vadjdim:1; + unsigned vsave:1; + unsigned vprocclass:3; + unsigned vregno:4; + union { + int varno; + chainp vstfdesc; /* points to (formals, expr) pair */ + struct intrpacked intrdesc; /* bits for intrinsic function */ + } vardesc; + struct dimblock *vdim; + int voffset; + }; + + +struct paramblock + { + char varname[VL]; + bigptr paramval; + } ; + + +struct exprblock + { + unsigned opcode:6; + bigptr leftp; + bigptr rightp; + }; + +struct dcomplex { + double dreal, dimag; +}; + +union constant + { + char *ccp; + ftnint ci; + double cd[2]; + struct dcomplex dc; + }; + +struct constblock + { + union constant fconst; + }; + + +struct listblock + { + chainp listp; + }; + + + +struct addrblock + { + int memno; + bigptr memoffset; + unsigned istemp:1; + unsigned ntempelt:10; + }; + + + +struct errorblock + { + int pad; + }; + + +struct dimblock + { + int ndim; + bigptr nelt; + bigptr baseoffset; + bigptr basexpr; + struct + { + bigptr dimsize; + bigptr dimexpr; + } dims[1]; + }; + + +struct impldoblock /* XXXX */ + { +#define isactive vtype +#define isbusy vclass + struct bigblock *varnp; + struct bigblock *varvp; + bigptr implb; + bigptr impub; + bigptr impstep; + ftnint impdiff; + ftnint implim; + chainp datalist; + }; + + +struct rplblock /* name replacement block */ + { + chainp nextp; + struct bigblock *rplnp; + ptr rplvp; + struct bigblock *rplxp; + int rpltag; + }; + + + +struct equivblock + { + ptr equivs; + unsigned eqvinit:1; + long int eqvtop; + long int eqvbottom; + } ; +#define eqvleng eqvtop + +extern struct equivblock eqvclass[ ]; + + +struct eqvchain + { + chainp nextp; + ptr eqvitem; + long int eqvoffset; + } ; + +union chainedblock + { + struct chain chain; + struct entrypoint entrypoint; + struct rplblock rplblock; + struct eqvchain eqvchain; + }; + + +struct bigblock { + unsigned tag:4; + unsigned vtype:4; + unsigned vclass:4; + unsigned vstg:4; + bigptr vleng; + union { + struct exprblock _expr; + struct addrblock _addr; + struct constblock _const; + struct errorblock _error; + struct listblock _list; + struct primblock _prim; + struct nameblock _name; + struct paramblock _param; + struct impldoblock _impldo; + } _u; +#define b_expr _u._expr +#define b_addr _u._addr +#define b_const _u._const +#define b_error _u._error +#define b_list _u._list +#define b_prim _u._prim +#define b_name _u._name +#define b_param _u._param +#define b_impldo _u._impldo +}; + +struct literal + { + short littype; + short litnum; + union { + ftnint litival; + double litdval; + struct { + char litclen; /* small integer */ + char litcstr[XL]; + } litcval; + } litval; + }; + +extern struct literal litpool[ ]; +extern int nliterals; + + + + + +/* popular functions with non integer return values */ +#define expptr bigptr +#define tagptr bigptr + +ptr cpblock(int ,void *); + +ptr ckalloc(int); +char *varstr(int, char *), *nounder(int, char *), *varunder(int, char *); +char *copyn(int, char *), *copys(char *); +chainp hookup(chainp, chainp), mkchain(bigptr, chainp); +ftnint convci(int, char *), iarrlen(struct bigblock *q); +ftnint lmin(ftnint, ftnint), lmax(ftnint, ftnint); +ftnint simoffset(expptr *); +char *memname(int, int), *convic(ftnint), *setdoto(char *); +double convcd(int, char *); +struct extsym *mkext(char *), + *newentry(struct bigblock *), + *comblock(int, char *s); +struct bigblock *mkname(int, char *); +struct labelblock *mklabel(ftnint); +struct bigblock *addrof(expptr), *call1(int, char *, expptr), + *call2(int, char *, expptr, expptr), + *call3(int, char *, expptr, expptr, expptr), + *call4(int, char *, expptr, expptr, expptr, expptr); +struct bigblock *call0(int, char *), *mkexpr(int, bigptr, bigptr); +struct bigblock *callk(int, char *, bigptr); + +struct bigblock *builtin(int, char *), *fmktemp(int, bigptr), + *mktmpn(int, int, bigptr), *nextdata(ftnint *, ftnint *), + *autovar(int, int, bigptr), *mklhs(struct bigblock *), + *mkaddr(struct bigblock *), *putconst(struct bigblock *), + *memversion(struct bigblock *); +struct bigblock *mkscalar(struct bigblock *np); +struct bigblock *realpart(struct bigblock *p); +struct bigblock *imagpart(struct bigblock *p); + +struct bigblock *mkintcon(ftnint), *mkbitcon(int, int, char *), + *mklogcon(int), *mkaddcon(int), *mkrealcon(int, double), + *mkstrcon(int, char *), *mkcxcon(bigptr,bigptr); +bigptr mkconst(int t); + +bigptr mklist(chainp p); +bigptr mkiodo(chainp, chainp); + + +bigptr mkconv(int, bigptr), + mkfunct(struct bigblock *), fixexpr(struct bigblock *), + fixtype(bigptr); + + +bigptr cpexpr(bigptr), mkprim(bigptr, struct bigblock *, bigptr, bigptr); +struct bigblock *mkarg(int, int); +struct bigblock *errnode(void); +void initkey(void), prtail(void), puteof(void), done(int); +void fileinit(void), procinit(void), endproc(void), doext(void), preven(int); +int inilex(char *), yyparse(void), newlabel(void), lengtype(int, int); +void err(char *, ...), warn(char *, ...), fatal(char *, ...), enddcl(void); +void p2pass(char *s), frexpr(bigptr), execerr(char *, ...); +void setimpl(int, ftnint, int, int), setlog(void), newproc(void); +void prdbginfo(void), impldcl(struct bigblock *p); +void putbracket(void), enddcl(void), doequiv(void); +void puthead(char *), startproc(struct extsym *, int); +void dclerr(char *s, struct bigblock *v), putforce(int, bigptr); +void entrypt(int, int, ftnint, struct extsym *, chainp); +void settype(struct bigblock *, int, int), putlabel(int); +void putbranch(struct bigblock *p), goret(int), putrbrack(int); +void prolog(struct entrypoint *, struct bigblock *), prendproc(void); +void prlocvar(char *, ftnint), prext(char *, ftnint, int); +void vardcl(struct bigblock *v), frchain(chainp *p); +void frtemp(struct bigblock *p), incomm(struct extsym *, struct bigblock *); +void setintr(struct bigblock * v), setext(struct bigblock * v); +struct uux { expptr lb, ub; }; +void setbound(struct bigblock *, int, struct uux []); +void setfmt(struct labelblock *lp), frdata(chainp), frrpl(void), + dataval(struct bigblock *, struct bigblock *), + consnegop(struct bigblock *p), exdo(int, chainp), exelse(void), + exendif(void), exif(bigptr), exelif(bigptr), + exequals(struct bigblock *, bigptr), + exassign(struct bigblock *, struct labelblock *), + exarif(bigptr, struct labelblock *, struct labelblock *, + struct labelblock *); + + + +int intrfunct(char s[VL]), eqn(int, char *, char *); +int fmtstmt(struct labelblock *lp); +int cktype(int, int, int); +int yylex(void), inregister(struct bigblock *); +int inilex(char *), iocname(void); +int maxtype(int, int), flog2(ftnint), hextoi(int); +int cmpstr(char *, char *, ftnint, ftnint); +int enregister(struct bigblock *np); +int conssgn(bigptr p); +int fixargs(int, struct bigblock *); +int addressable(bigptr p); + +void prlabel(int); +void prconi(FILE *, int, ftnint); +void prcona(ftnint); +void prconr(FILE *, int, double); +void prarif(bigptr, int, int, int); +void putstr(char *, ftnint); +NODE *putex1(bigptr p); +void puteq(bigptr, bigptr); +void popstack(chainp *p); +void consconv(int, union constant *, int, union constant *); +void yyerror(char *s); +void enddo(int); +void doinclude(char *); +void flline(void); +void startioctl(void); +void endioctl(void), endio(void), ioclause(int, bigptr), doio(chainp); +void excall(struct bigblock *, struct bigblock *, int, struct labelblock *[]); +void exreturn(expptr p); +void exstop(int, expptr); +void exgoto(struct labelblock *); +void exasgoto(bigptr); +void putcmgo(expptr, int, struct labelblock *[]); +void putexpr(expptr p); +void putif(expptr, int); +void putgoto(int); +void deregister(struct bigblock *np); +NODE *putx(expptr p); +void cpn(int, char *, char *); +void prcmgoto(expptr, int, int, int); +char *lexline(ftnint *n); +bigptr suboffset(struct bigblock *p); +struct bigblock *intraddr(struct bigblock *np); +struct bigblock *intrcall(bigptr, bigptr, int); +void setloc(int); +void prnloc(char *name); +void fprint(bigptr p, int indx); +void ckfree(void *p); + +#undef expptr +#undef tagptr + +#define err1 err +#define err2 err +#define warn1 warn +#define fatal1 fatal diff --git a/compilers/pcc/pcc-1.0.0/f77/fcom/equiv.c b/compilers/pcc/pcc-1.0.0/f77/fcom/equiv.c new file mode 100644 index 00000000..7e83d153 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/fcom/equiv.c @@ -0,0 +1,309 @@ +/* $Id: equiv.c,v 1.11 2008/05/11 15:28:03 ragge Exp $ */ +/* + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code and documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditionsand the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "defines.h" +#include "defs.h" + + +/* ROUTINES RELATED TO EQUIVALENCE CLASS PROCESSING */ +LOCAL void eqvcommon(struct equivblock *, int, ftnint); +LOCAL void eqveqv(int, int, ftnint); +LOCAL void freqchain(struct equivblock *p); +LOCAL int nsubs(struct bigblock *p); + +/* called at end of declarations section to process chains + created by EQUIVALENCE statements + */ +void +doequiv() +{ +register int i; +int inequiv, comno, ovarno; +ftnint comoffset, offset, leng; +register struct equivblock *p; +register chainp q; +struct bigblock *itemp; +register struct bigblock *np; +bigptr offp; +int ns; +chainp cp; + +ovarno = comoffset = offset = 0; /* XXX gcc */ +for(i = 0 ; i < nequiv ; ++i) + { + p = &eqvclass[i]; + p->eqvbottom = p->eqvtop = 0; + comno = -1; + + for(q = p->equivs ; q ; q = q->eqvchain.nextp) + { + itemp = q->eqvchain.eqvitem; + vardcl(np = itemp->b_prim.namep); + if(itemp->b_prim.argsp || itemp->b_prim.fcharp) + { + if(np->b_name.vdim!=NULL && np->b_name.vdim->ndim>1 && + nsubs(itemp->b_prim.argsp)==1 ) + { + if(! ftn66flag) + warn("1-dim subscript in EQUIVALENCE"); + cp = NULL; + ns = np->b_name.vdim->ndim; + while(--ns > 0) + cp = mkchain( MKICON(1), cp); + itemp->b_prim.argsp->b_list.listp->chain.nextp = cp; + } + offp = suboffset(itemp); + } + else offp = MKICON(0); + if(ISICON(offp)) + offset = q->eqvchain.eqvoffset = offp->b_const.fconst.ci; + else { + dclerr("nonconstant subscript in equivalence ", np); + np = NULL; + goto endit; + } + if( (leng = iarrlen(np)) < 0) + { + dclerr("adjustable in equivalence", np); + np = NULL; + goto endit; + } + p->eqvbottom = lmin(p->eqvbottom, -offset); + p->eqvtop = lmax(p->eqvtop, leng-offset); + + switch(np->vstg) + { + case STGUNKNOWN: + case STGBSS: + case STGEQUIV: + break; + + case STGCOMMON: + comno = np->b_name.vardesc.varno; + comoffset = np->b_name.voffset + offset; + break; + + default: + dclerr("bad storage class in equivalence", np); + np = NULL; + goto endit; + } + endit: + frexpr(offp); + q->eqvchain.eqvitem = np; + } + + if(comno >= 0) + eqvcommon(p, comno, comoffset); + else for(q = p->equivs ; q ; q = q->eqvchain.nextp) + { + if((np = q->eqvchain.eqvitem)) + { + inequiv = NO; + if(np->vstg==STGEQUIV) { + if( (ovarno = np->b_name.vardesc.varno) == i) + { + if(np->b_name.voffset + q->eqvchain.eqvoffset != 0) + dclerr("inconsistent equivalence", np); + } + else { + offset = np->b_name.voffset; + inequiv = YES; + } + } + np->vstg = STGEQUIV; + np->b_name.vardesc.varno = i; + np->b_name.voffset = - q->eqvchain.eqvoffset; + + if(inequiv) + eqveqv(i, ovarno, q->eqvchain.eqvoffset + offset); + } + } + } + +for(i = 0 ; i < nequiv ; ++i) + { + p = & eqvclass[i]; + if(p->eqvbottom!=0 || p->eqvtop!=0) + { + for(q = p->equivs ; q; q = q->eqvchain.nextp) + { + np = q->eqvchain.eqvitem; + np->b_name.voffset -= p->eqvbottom; + if(np->b_name.voffset % typealign[np->vtype] != 0) + dclerr("bad alignment forced by equivalence", np); + } + p->eqvtop -= p->eqvbottom; + p->eqvbottom = 0; + } + freqchain(p); + } +} + + + + + +/* put equivalence chain p at common block comno + comoffset */ + +LOCAL void eqvcommon(p, comno, comoffset) +struct equivblock *p; +int comno; +ftnint comoffset; +{ +int ovarno; +ftnint k, offq; +register struct bigblock *np; +register chainp q; + +if(comoffset + p->eqvbottom < 0) + { + err1("attempt to extend common %s backward", + nounder(XL, extsymtab[comno].extname) ); + freqchain(p); + return; + } + +if( (k = comoffset + p->eqvtop) > extsymtab[comno].extleng) + extsymtab[comno].extleng = k; + +for(q = p->equivs ; q ; q = q->eqvchain.nextp) + if((np = q->eqvchain.eqvitem)) + { + switch(np->vstg) + { + case STGUNKNOWN: + case STGBSS: + np->vstg = STGCOMMON; + np->b_name.vardesc.varno = comno; + np->b_name.voffset = comoffset - q->eqvchain.eqvoffset; + break; + + case STGEQUIV: + ovarno = np->b_name.vardesc.varno; + offq = comoffset - q->eqvchain.eqvoffset - np->b_name.voffset; + np->vstg = STGCOMMON; + np->b_name.vardesc.varno = comno; + np->b_name.voffset = comoffset - q->eqvchain.eqvoffset; + if(ovarno != (p - eqvclass)) + eqvcommon(&eqvclass[ovarno], comno, offq); + break; + + case STGCOMMON: + if(comno != np->b_name.vardesc.varno || + comoffset != np->b_name.voffset+q->eqvchain.eqvoffset) + dclerr("inconsistent common usage", np); + break; + + + default: + fatal1("eqvcommon: impossible vstg %d", np->vstg); + } + } + +freqchain(p); +p->eqvbottom = p->eqvtop = 0; +} + + +/* put all items on ovarno chain on front of nvarno chain + * adjust offsets of ovarno elements and top and bottom of nvarno chain + */ + +LOCAL void eqveqv(nvarno, ovarno, delta) +int ovarno, nvarno; +ftnint delta; +{ +register struct equivblock *p0, *p; +register struct nameblock *np; +chainp q, q1; + +p0 = eqvclass + nvarno; +p = eqvclass + ovarno; +p0->eqvbottom = lmin(p0->eqvbottom, p->eqvbottom - delta); +p0->eqvtop = lmax(p0->eqvtop, p->eqvtop - delta); +p->eqvbottom = p->eqvtop = 0; + +for(q = p->equivs ; q ; q = q1) + { + q1 = q->eqvchain.nextp; + if( (np = q->eqvchain.eqvitem) && np->vardesc.varno==ovarno) + { + q->eqvchain.nextp = p0->equivs; + p0->equivs = q; + q->eqvchain.eqvoffset -= delta; + np->vardesc.varno = nvarno; + np->voffset -= delta; + } + else ckfree(q); + } +p->equivs = NULL; +} + + + + +LOCAL void +freqchain(p) +register struct equivblock *p; +{ +register chainp q, oq; + +for(q = p->equivs ; q ; q = oq) + { + oq = q->eqvchain.nextp; + ckfree(q); + } +p->equivs = NULL; +} + + + + + +LOCAL int +nsubs(p) +register struct bigblock *p; +{ +register int n; +register chainp q; + +n = 0; +if(p) + for(q = p->b_list.listp ; q ; q = q->chain.nextp) + ++n; + +return(n); +} diff --git a/compilers/pcc/pcc-1.0.0/f77/fcom/error.c b/compilers/pcc/pcc-1.0.0/f77/fcom/error.c new file mode 100644 index 00000000..d2fbabda --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/fcom/error.c @@ -0,0 +1,121 @@ +/* $Id: error.c,v 1.8 2008/05/10 07:53:41 ragge Exp $ */ +/* + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code and documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "defines.h" +#include "defs.h" + +void +warn(char *s, ...) +{ + va_list ap; + + if(nowarnflag) + return; + + va_start(ap, s); + fprintf(diagfile, "Warning on line %d of %s: ", lineno, infname); + vfprintf(diagfile, s, ap); + fprintf(diagfile, "\n"); + va_end(ap); + ++nwarn; +} + +void +err(char *s, ...) +{ + va_list ap; + + va_start(ap, s); + fprintf(diagfile, "Error on line %d of %s: ", lineno, infname); + vfprintf(diagfile, s, ap); + fprintf(diagfile, "\n"); + va_end(ap); + ++nerr; +} + +void +yyerror(s) +char *s; +{ err(s); } + + +void +dclerr(s, v) + char *s; + struct bigblock *v; +{ + char buff[100]; + + if(v) { + sprintf(buff, "Declaration error for %s: %s", + varstr(VL, v->b_name.varname), s); + err( buff); + } else + err1("Declaration error %s", s); +} + + +void +execerr(char *s, ...) +{ + va_list ap; + + va_start(ap, s); + fprintf(diagfile, "Error on line %d of %s: Execution error ", + lineno, infname); + vfprintf(diagfile, s, ap); + fprintf(diagfile, "\n"); + va_end(ap); + ++nerr; +} + +void +fatal(char *s, ...) +{ + va_list ap; + + va_start(ap, s); + fprintf(diagfile, "Compiler error line %d of %s: ", lineno, infname); + vfprintf(diagfile, s, ap); + fprintf(diagfile, "\n"); + va_end(ap); + + if(debugflag) + abort(); + done(3); + exit(3); +} diff --git a/compilers/pcc/pcc-1.0.0/f77/fcom/exec.c b/compilers/pcc/pcc-1.0.0/f77/fcom/exec.c new file mode 100644 index 00000000..6584e8ac --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/fcom/exec.c @@ -0,0 +1,591 @@ +/* $Id: exec.c,v 1.14 2008/05/11 15:28:03 ragge Exp $ */ +/* + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code and documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include + +#include "defines.h" +#include "defs.h" + +/* Logical IF codes +*/ +LOCAL void exar2(int, bigptr, int, int); +LOCAL void pushctl(int code); +LOCAL void popctl(void); +LOCAL void poplab(void); +LOCAL void mkstfunct(struct bigblock *, bigptr); + +void +exif(p) +bigptr p; +{ +pushctl(CTLIF); +ctlstack->elselabel = newlabel(); +putif(p, ctlstack->elselabel); +} + + +void +exelif(p) +bigptr p; +{ +if(ctlstack->ctltype == CTLIF) + { + if(ctlstack->endlabel == 0) + ctlstack->endlabel = newlabel(); + putgoto(ctlstack->endlabel); + putlabel(ctlstack->elselabel); + ctlstack->elselabel = newlabel(); + putif(p, ctlstack->elselabel); + } + +else execerr("elseif out of place", 0); +} + + + + +void +exelse() +{ +if(ctlstack->ctltype==CTLIF) + { + if(ctlstack->endlabel == 0) + ctlstack->endlabel = newlabel(); + putgoto( ctlstack->endlabel ); + putlabel(ctlstack->elselabel); + ctlstack->ctltype = CTLELSE; + } + +else execerr("else out of place", 0); +} + +void +exendif() +{ +if(ctlstack->ctltype == CTLIF) + { + putlabel(ctlstack->elselabel); + if(ctlstack->endlabel) + putlabel(ctlstack->endlabel); + popctl(); + } +else if(ctlstack->ctltype == CTLELSE) + { + putlabel(ctlstack->endlabel); + popctl(); + } + +else execerr("endif out of place", 0); +} + + + +LOCAL void +pushctl(code) +int code; +{ +register int i; + +if(++ctlstack >= lastctl) + fatal("nesting too deep"); +ctlstack->ctltype = code; +for(i = 0 ; i < 4 ; ++i) + ctlstack->ctlabels[i] = 0; +++blklevel; +} + + +LOCAL void +popctl() +{ +if( ctlstack-- < ctls ) + fatal("control stack empty"); +--blklevel; +poplab(); +} + + + +LOCAL void +poplab() +{ +register struct labelblock *lp; + +for(lp = labeltab ; lp < highlabtab ; ++lp) + if(lp->labdefined) + { + /* mark all labels in inner blocks unreachable */ + if(lp->blklevel > blklevel) + lp->labinacc = YES; + } + else if(lp->blklevel > blklevel) + { + /* move all labels referred to in inner blocks out a level */ + lp->blklevel = blklevel; + } +} + + + +/* BRANCHING CODE +*/ +void +exgoto(lab) +struct labelblock *lab; +{ +putgoto(lab->labelno); +} + + + + +/* + * Found an assignment expression. + */ +void +exequals(struct bigblock *lp, bigptr rp) +{ + if(lp->tag != TPRIM) { + err("assignment to a non-variable"); + frexpr(lp); + frexpr(rp); + } else if(lp->b_prim.namep->vclass!=CLVAR && lp->b_prim.argsp) { + if(parstate >= INEXEC) + err("statement function amid executables"); + else + mkstfunct(lp, rp); + } else { + if(parstate < INDATA) + enddcl(); + puteq(mklhs(lp), rp); + } +} + +/* + * Create a statement function; e.g. like "f(i)=i*i" + */ +void +mkstfunct(struct bigblock *lp, bigptr rp) +{ + struct bigblock *p; + struct bigblock *np; + chainp args; + + np = lp->b_prim.namep; + if(np->vclass == CLUNKNOWN) + np->vclass = CLPROC; + else { + dclerr("redeclaration of statement function", np); + return; + } + + np->b_name.vprocclass = PSTFUNCT; + np->vstg = STGSTFUNCT; + impldcl(np); + args = (lp->b_prim.argsp ? lp->b_prim.argsp->b_list.listp : NULL); + np->b_name.vardesc.vstfdesc = mkchain((void *)args, (void *)rp); + + for( ; args ; args = args->chain.nextp) + if( (p = args->chain.datap)->tag!=TPRIM || + p->b_prim.argsp || p->b_prim.fcharp || p->b_prim.lcharp) + err("non-variable argument in statement function definition"); + else { + vardcl(args->chain.datap = p->b_prim.namep); + ckfree(p); + } +} + + +void +excall(name, args, nstars, labels) +struct bigblock *name; +struct bigblock *args; +int nstars; +struct labelblock *labels[ ]; +{ +register bigptr p; + +settype(name, TYSUBR, 0); +p = mkfunct( mkprim(name, args, NULL, NULL) ); +p->vtype = p->b_expr.leftp->vtype = TYINT; +if(nstars > 0) + putcmgo(p, nstars, labels); +else putexpr(p); +} + + +void +exstop(stop, p) +int stop; +register bigptr p; +{ +char *q; +int n; + +if(p) + { + if( ! ISCONST(p) ) + { + execerr("pause/stop argument must be constant", 0); + frexpr(p); + p = mkstrcon(0, 0); + } + else if( ISINT(p->vtype) ) + { + q = convic(p->b_const.fconst.ci); + n = strlen(q); + if(n > 0) + { + p->b_const.fconst.ccp = copyn(n, q); + p->vtype = TYCHAR; + p->vleng = MKICON(n); + } + else + p = mkstrcon(0, 0); + } + else if(p->vtype != TYCHAR) + { + execerr("pause/stop argument must be integer or string", 0); + p = mkstrcon(0, 0); + } + } +else p = mkstrcon(0, 0); + +putexpr( call1(TYSUBR, (stop ? "s_stop" : "s_paus"), p) ); +} + +/* DO LOOP CODE */ + +#define DOINIT par[0] +#define DOLIMIT par[1] +#define DOINCR par[2] + +#define VARSTEP 0 +#define POSSTEP 1 +#define NEGSTEP 2 + +void +exdo(range, spec) +int range; +chainp spec; +{ +register bigptr p, q; +bigptr q1; +register struct bigblock *np; +chainp cp; +register int i; +int dotype, incsign = 0; /* XXX gcc */ +struct bigblock *dovarp, *dostgp; +bigptr par[3]; + +pushctl(CTLDO); +dorange = ctlstack->dolabel = range; +np = spec->chain.datap; +ctlstack->donamep = NULL; +if(np->b_name.vdovar) + { + err1("nested loops with variable %s", varstr(VL,np->b_name.varname)); + ctlstack->donamep = NULL; + return; + } + +dovarp = mklhs( mkprim(np, 0,0,0) ); +if( ! ONEOF(dovarp->vtype, MSKINT|MSKREAL) ) + { + err("bad type on do variable"); + return; + } +ctlstack->donamep = np; + +np->b_name.vdovar = YES; +if( enregister(np) ) + { + /* stgp points to a storage version, varp to a register version */ + dostgp = dovarp; + dovarp = mklhs( mkprim(np, 0,0,0) ); + } +else + dostgp = NULL; +dotype = dovarp->vtype; + +for(i=0 , cp = spec->chain.nextp ; cp!=NULL && i<3 ; cp = cp->chain.nextp) + { + p = par[i++] = fixtype(cp->chain.datap); + if( ! ONEOF(p->vtype, MSKINT|MSKREAL) ) + { + err("bad type on DO parameter"); + return; + } + } + +frchain(&spec); +switch(i) + { + case 0: + case 1: + err("too few DO parameters"); + return; + + default: + err("too many DO parameters"); + return; + + case 2: + DOINCR = MKICON(1); + + case 3: + break; + } + +ctlstack->endlabel = newlabel(); +ctlstack->dobodylabel = newlabel(); + +if( ISCONST(DOLIMIT) ) + ctlstack->domax = mkconv(dotype, DOLIMIT); +else + ctlstack->domax = fmktemp(dotype, NULL); + +if( ISCONST(DOINCR) ) + { + ctlstack->dostep = mkconv(dotype, DOINCR); + if( (incsign = conssgn(ctlstack->dostep)) == 0) + err("zero DO increment"); + ctlstack->dostepsign = (incsign > 0 ? POSSTEP : NEGSTEP); + } +else + { + ctlstack->dostep = fmktemp(dotype, NULL); + ctlstack->dostepsign = VARSTEP; + ctlstack->doposlabel = newlabel(); + ctlstack->doneglabel = newlabel(); + } + +if( ISCONST(ctlstack->domax) && ISCONST(DOINIT) && ctlstack->dostepsign!=VARSTEP) + { + puteq(cpexpr(dovarp), cpexpr(DOINIT)); + if( onetripflag ) + frexpr(DOINIT); + else + { + q = mkexpr(OPPLUS, MKICON(1), + mkexpr(OPMINUS, cpexpr(ctlstack->domax), cpexpr(DOINIT)) ); + if(incsign != conssgn(q)) + { + warn("DO range never executed"); + putgoto(ctlstack->endlabel); + } + frexpr(q); + } + } +else if(ctlstack->dostepsign!=VARSTEP && !onetripflag) + { + if( ISCONST(ctlstack->domax) ) + q = cpexpr(ctlstack->domax); + else + q = mkexpr(OPASSIGN, cpexpr(ctlstack->domax), DOLIMIT); + + q1 = mkexpr(OPASSIGN, cpexpr(dovarp), DOINIT); + q = mkexpr( (ctlstack->dostepsign==POSSTEP ? OPLE : OPGE), q1, q); + putif(q, ctlstack->endlabel); + } +else + { + if(! ISCONST(ctlstack->domax) ) + puteq( cpexpr(ctlstack->domax), DOLIMIT); + q = DOINIT; + if( ! onetripflag ) + q = mkexpr(OPMINUS, q, + mkexpr(OPASSIGN, cpexpr(ctlstack->dostep), DOINCR) ); + puteq( cpexpr(dovarp), q); + if(onetripflag && ctlstack->dostepsign==VARSTEP) + puteq( cpexpr(ctlstack->dostep), DOINCR); + } + +if(ctlstack->dostepsign == VARSTEP) + { + if(onetripflag) + putgoto(ctlstack->dobodylabel); + else + putif( mkexpr(OPGE, cpexpr(ctlstack->dostep), MKICON(0)), + ctlstack->doneglabel ); + putlabel(ctlstack->doposlabel); + + p = cpexpr(dovarp); + putif( mkexpr(OPLE, mkexpr(OPASSIGN, p, + mkexpr(OPPLUS, cpexpr(dovarp), cpexpr(ctlstack->dostep))), + cpexpr(ctlstack->domax)), ctlstack->endlabel); + } +putlabel(ctlstack->dobodylabel); +if(dostgp) + puteq(dostgp, cpexpr(dovarp)); +frexpr(dovarp); +} + +/* + * Reached the end of a DO statement. + */ +void +enddo(int here) +{ + register struct ctlframe *q; + register bigptr t; + struct bigblock *np; + struct bigblock *ap; + register int i; + + while(here == dorange) { + if((np = ctlstack->donamep)) { + + t = mklhs(mkprim(ctlstack->donamep, 0,0 ,0)); + t = mkexpr(OPASSIGN, cpexpr(t), + mkexpr(OPPLUS, t, cpexpr(ctlstack->dostep))); + + if(ctlstack->dostepsign == VARSTEP) { + putif( mkexpr(OPLE, cpexpr(ctlstack->dostep), + MKICON(0)), ctlstack->doposlabel); + putlabel(ctlstack->doneglabel); + putif( mkexpr(OPLT, t, ctlstack->domax), + ctlstack->dobodylabel); + } else + putif( mkexpr( (ctlstack->dostepsign==POSSTEP ? + OPGT : OPLT), t, ctlstack->domax), + ctlstack->dobodylabel); + putlabel(ctlstack->endlabel); + if((ap = memversion(np))) + puteq(ap, mklhs( mkprim(np,0,0,0)) ); + for(i = 0 ; i < 4 ; ++i) + ctlstack->ctlabels[i] = 0; + deregister(ctlstack->donamep); + ctlstack->donamep->b_name.vdovar = NO; + frexpr(ctlstack->dostep); + } + + popctl(); + dorange = 0; + for(q = ctlstack ; q>=ctls ; --q) + if(q->ctltype == CTLDO) { + dorange = q->dolabel; + break; + } + } +} + +void +exassign(vname, labelval) +struct bigblock *vname; +struct labelblock *labelval; +{ +struct bigblock *p; + +p = mklhs(mkprim(vname,0,0,0)); +if( ! ONEOF(p->vtype, MSKINT|MSKADDR) ) + err("noninteger assign variable"); +else + puteq(p, mkaddcon(labelval->labelno) ); +} + + +void +exarif(expr, neglab, zerlab, poslab) +bigptr expr; +struct labelblock *neglab, *zerlab, *poslab; +{ +register int lm, lz, lp; + +lm = neglab->labelno; +lz = zerlab->labelno; +lp = poslab->labelno; +expr = fixtype(expr); + +if( ! ONEOF(expr->vtype, MSKINT|MSKREAL) ) + { + err("invalid type of arithmetic if expression"); + frexpr(expr); + } +else + { + if(lm == lz) + exar2(OPLE, expr, lm, lp); + else if(lm == lp) + exar2(OPNE, expr, lm, lz); + else if(lz == lp) + exar2(OPGE, expr, lz, lm); + else + prarif(expr, lm, lz, lp); + } +} + + + +LOCAL void exar2(op, e, l1, l2) +int op; +bigptr e; +int l1, l2; +{ +putif( mkexpr(op, e, MKICON(0)), l2); +putgoto(l1); +} + +void +exreturn(p) +register bigptr p; +{ +if(p && (proctype!=TYSUBR || procclass!=CLPROC) ) + { + err("alternate return in nonsubroutine"); + p = 0; + } + +if(p) + { + putforce(TYINT, p); + putgoto(retlabel); + } +else + putgoto(procclass==TYSUBR ? ret0label : retlabel); +} + + +void +exasgoto(labvar) +bigptr labvar; +{ +register struct bigblock *p; + +p = mklhs( mkprim(labvar,0,0,0) ); +if( ! ISINT(p->vtype) ) + err("assigned goto variable must be integer"); +else + putbranch(p); +} diff --git a/compilers/pcc/pcc-1.0.0/f77/fcom/expr.c b/compilers/pcc/pcc-1.0.0/f77/fcom/expr.c new file mode 100644 index 00000000..0f4d24b4 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/fcom/expr.c @@ -0,0 +1,2179 @@ +/* $Id: expr.c,v 1.20 2008/05/11 15:28:03 ragge Exp $ */ +/* + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code and documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditionsand the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include + +#include "defines.h" +#include "defs.h" + +/* little routines to create constant blocks */ +LOCAL int letter(int c); +LOCAL void conspower(union constant *, struct bigblock *, ftnint); +LOCAL void consbinop(int, int, union constant *, union constant *, + union constant *); +LOCAL void zdiv(struct dcomplex *, struct dcomplex *, struct dcomplex *); +LOCAL struct bigblock *stfcall(struct bigblock *, struct bigblock *); +LOCAL bigptr mkpower(struct bigblock *p); +LOCAL bigptr fold(struct bigblock *e); +LOCAL bigptr subcheck(struct bigblock *, bigptr); + +struct bigblock *mkconst(t) +register int t; +{ +register struct bigblock *p; + +p = BALLO(); +p->tag = TCONST; +p->vtype = t; +return(p); +} + + +struct bigblock *mklogcon(l) +register int l; +{ +register struct bigblock * p; + +p = mkconst(TYLOGICAL); +p->b_const.fconst.ci = l; +return(p); +} + + + +struct bigblock *mkintcon(l) +ftnint l; +{ +register struct bigblock *p; + +p = mkconst(TYLONG); +p->b_const.fconst.ci = l; +#ifdef MAXSHORT + if(l >= -MAXSHORT && l <= MAXSHORT) + p->vtype = TYSHORT; +#endif +return(p); +} + + + +struct bigblock *mkaddcon(l) +register int l; +{ +register struct bigblock *p; + +p = mkconst(TYADDR); +p->b_const.fconst.ci = l; +return(p); +} + + + +struct bigblock *mkrealcon(t, d) +register int t; +double d; +{ +register struct bigblock *p; + +p = mkconst(t); +p->b_const.fconst.cd[0] = d; +return(p); +} + + +struct bigblock *mkbitcon(shift, leng, s) +int shift; +int leng; +char *s; +{ +register struct bigblock *p; + +p = mkconst(TYUNKNOWN); +p->b_const.fconst.ci = 0; +while(--leng >= 0) + if(*s != ' ') + p->b_const.fconst.ci = (p->b_const.fconst.ci << shift) | hextoi(*s++); +return(p); +} + + + + + +struct bigblock *mkstrcon(l,v) +int l; +register char *v; +{ +register struct bigblock *p; +register char *s; + +p = mkconst(TYCHAR); +p->vleng = MKICON(l); +p->b_const.fconst.ccp = s = (char *) ckalloc(l); +while(--l >= 0) + *s++ = *v++; +return(p); +} + + +struct bigblock *mkcxcon(realp,imagp) +register bigptr realp, imagp; +{ +int rtype, itype; +register struct bigblock *p; + +rtype = realp->vtype; +itype = imagp->vtype; + +if( ISCONST(realp) && ISNUMERIC(rtype) && ISCONST(imagp) && ISNUMERIC(itype) ) + { + p = mkconst( (rtype==TYDREAL||itype==TYDREAL) ? TYDCOMPLEX : TYCOMPLEX ); + if( ISINT(rtype) ) + p->b_const.fconst.cd[0] = realp->b_const.fconst.ci; + else p->b_const.fconst.cd[0] = realp->b_const.fconst.cd[0]; + if( ISINT(itype) ) + p->b_const.fconst.cd[1] = imagp->b_const.fconst.ci; + else p->b_const.fconst.cd[1] = imagp->b_const.fconst.cd[0]; + } +else + { + err("invalid complex constant"); + p = errnode(); + } + +frexpr(realp); +frexpr(imagp); +return(p); +} + + +struct bigblock *errnode() +{ +struct bigblock *p; +p = BALLO(); +p->tag = TERROR; +p->vtype = TYERROR; +return(p); +} + + + + + +bigptr mkconv(t, p) +register int t; +register bigptr p; +{ +register bigptr q; + +if(t==TYUNKNOWN || t==TYERROR) + fatal1("mkconv of impossible type %d", t); +if(t == p->vtype) + return(p); + +else if( ISCONST(p) && p->vtype!=TYADDR) + { + q = mkconst(t); + consconv(t, &(q->b_const.fconst), p->vtype, &(p->b_const.fconst)); + frexpr(p); + } +else + { + q = mkexpr(OPCONV, p, 0); + q->vtype = t; + } +return(q); +} + + + +struct bigblock *addrof(p) +bigptr p; +{ +return( mkexpr(OPADDR, p, NULL) ); +} + + + +bigptr +cpexpr(p) +register bigptr p; +{ +register bigptr e; +int tag; +register chainp ep, pp; + +#if 0 +static int blksize[ ] = { 0, sizeof(struct nameblock), sizeof(struct constblock), + sizeof(struct exprblock), sizeof(struct addrblock), + sizeof(struct primblock), sizeof(struct listblock), + sizeof(struct errorblock) + }; +#endif + +if(p == NULL) + return(NULL); + +if( (tag = p->tag) == TNAME) + return(p); + +#if 0 +e = cpblock( blksize[p->tag] , p); +#else +e = cpblock( sizeof(struct bigblock) , p); +#endif + +switch(tag) + { + case TCONST: + if(e->vtype == TYCHAR) + { + e->b_const.fconst.ccp = copyn(1+strlen(e->b_const.fconst.ccp), e->b_const.fconst.ccp); + e->vleng = cpexpr(e->vleng); + } + case TERROR: + break; + + case TEXPR: + e->b_expr.leftp = cpexpr(p->b_expr.leftp); + e->b_expr.rightp = cpexpr(p->b_expr.rightp); + break; + + case TLIST: + if((pp = p->b_list.listp)) + { + ep = e->b_list.listp = mkchain( cpexpr(pp->chain.datap), NULL); + for(pp = pp->chain.nextp ; pp ; pp = pp->chain.nextp) + ep = ep->chain.nextp = mkchain( cpexpr(pp->chain.datap), NULL); + } + break; + + case TADDR: + e->vleng = cpexpr(e->vleng); + e->b_addr.memoffset = cpexpr(e->b_addr.memoffset); + e->b_addr.istemp = NO; + break; + + case TPRIM: + e->b_prim.argsp = cpexpr(e->b_prim.argsp); + e->b_prim.fcharp = cpexpr(e->b_prim.fcharp); + e->b_prim.lcharp = cpexpr(e->b_prim.lcharp); + break; + + default: + fatal1("cpexpr: impossible tag %d", tag); + } + +return(e); +} + +void +frexpr(p) +register bigptr p; +{ +register chainp q; + +if(p == NULL) + return; + +switch(p->tag) + { + case TCONST: + if( ISCHAR(p) ) + { + ckfree(p->b_const.fconst.ccp); + frexpr(p->vleng); + } + break; + + case TADDR: + if(p->b_addr.istemp) + { + frtemp(p); + return; + } + frexpr(p->vleng); + frexpr(p->b_addr.memoffset); + break; + + case TERROR: + break; + + case TNAME: + return; + + case TPRIM: + frexpr(p->b_prim.argsp); + frexpr(p->b_prim.fcharp); + frexpr(p->b_prim.lcharp); + break; + + case TEXPR: + frexpr(p->b_expr.leftp); + if(p->b_expr.rightp) + frexpr(p->b_expr.rightp); + break; + + case TLIST: + for(q = p->b_list.listp ; q ; q = q->chain.nextp) + frexpr(q->chain.datap); + frchain( &(p->b_list.listp) ); + break; + + default: + fatal1("frexpr: impossible tag %d", p->tag); + } + +ckfree(p); +} + +/* fix up types in expression; replace subtrees and convert + names to address blocks */ + +bigptr fixtype(p) +register bigptr p; +{ + +if(p == 0) + return(0); + +switch(p->tag) + { + case TCONST: + if( ! ONEOF(p->vtype, MSKINT|MSKLOGICAL|MSKADDR) ) + p = putconst(p); + return(p); + + case TADDR: + p->b_addr.memoffset = fixtype(p->b_addr.memoffset); + return(p); + + case TERROR: + return(p); + + default: + fatal1("fixtype: impossible tag %d", p->tag); + + case TEXPR: + return( fixexpr(p) ); + + case TLIST: + return( p ); + + case TPRIM: + if(p->b_prim.argsp && p->b_prim.namep->vclass!=CLVAR) + return( mkfunct(p) ); + else return( mklhs(p) ); + } +} + + + + + +/* special case tree transformations and cleanups of expression trees */ + +bigptr fixexpr(p) +register struct bigblock *p; +{ +bigptr lp; +register bigptr rp; +register bigptr q; +int opcode, ltype, rtype, ptype, mtype; + +if(p->tag == TERROR) + return(p); +else if(p->tag != TEXPR) + fatal1("fixexpr: invalid tag %d", p->tag); +opcode = p->b_expr.opcode; +lp = p->b_expr.leftp = fixtype(p->b_expr.leftp); +ltype = lp->vtype; +if(opcode==OPASSIGN && lp->tag!=TADDR) + { + err("left side of assignment must be variable"); + frexpr(p); + return( errnode() ); + } + +if(p->b_expr.rightp) + { + rp = p->b_expr.rightp = fixtype(p->b_expr.rightp); + rtype = rp->vtype; + } +else + { + rp = NULL; + rtype = 0; + } + +/* force folding if possible */ +if( ISCONST(lp) && (rp==NULL || ISCONST(rp)) ) + { + q = mkexpr(opcode, lp, rp); + if( ISCONST(q) ) + return(q); + ckfree(q); /* constants did not fold */ + } + +if( (ptype = cktype(opcode, ltype, rtype)) == TYERROR) + { + frexpr(p); + return( errnode() ); + } + +switch(opcode) + { + case OPCONCAT: + if(p->vleng == NULL) + p->vleng = mkexpr(OPPLUS, cpexpr(lp->vleng), + cpexpr(rp->vleng) ); + break; + + case OPASSIGN: + if(ltype == rtype) + break; + if( ! ISCONST(rp) && ISREAL(ltype) && ISREAL(rtype) ) + break; + if( ISCOMPLEX(ltype) || ISCOMPLEX(rtype) ) + break; + if( ONEOF(ltype, MSKADDR|MSKINT) && ONEOF(rtype, MSKADDR|MSKINT) + && typesize[ltype]>=typesize[rtype] ) + break; + p->b_expr.rightp = fixtype( mkconv(ptype, rp) ); + break; + + case OPSLASH: + if( ISCOMPLEX(rtype) ) + { + p = call2(ptype, ptype==TYCOMPLEX? "c_div" : "z_div", + mkconv(ptype, lp), mkconv(ptype, rp) ); + break; + } + case OPPLUS: + case OPMINUS: + case OPSTAR: + case OPMOD: + if(ptype==TYDREAL && ( (ltype==TYREAL && ! ISCONST(lp) ) || + (rtype==TYREAL && ! ISCONST(rp) ) )) + break; + if( ISCOMPLEX(ptype) ) + break; + if(ltype != ptype) + p->b_expr.leftp = fixtype(mkconv(ptype,lp)); + if(rtype != ptype) + p->b_expr.rightp = fixtype(mkconv(ptype,rp)); + break; + + case OPPOWER: + return( mkpower(p) ); + + case OPLT: + case OPLE: + case OPGT: + case OPGE: + case OPEQ: + case OPNE: + if(ltype == rtype) + break; + mtype = cktype(OPMINUS, ltype, rtype); + if(mtype==TYDREAL && ( (ltype==TYREAL && ! ISCONST(lp)) || + (rtype==TYREAL && ! ISCONST(rp)) )) + break; + if( ISCOMPLEX(mtype) ) + break; + if(ltype != mtype) + p->b_expr.leftp = fixtype(mkconv(mtype,lp)); + if(rtype != mtype) + p->b_expr.rightp = fixtype(mkconv(mtype,rp)); + break; + + + case OPCONV: + ptype = cktype(OPCONV, p->vtype, ltype); + if(lp->tag==TEXPR && lp->b_expr.opcode==OPCOMMA) + { + lp->b_expr.rightp = fixtype( mkconv(ptype, lp->b_expr.rightp) ); + ckfree(p); + p = lp; + } + break; + + case OPADDR: + if(lp->tag==TEXPR && lp->b_expr.opcode==OPADDR) + fatal("addr of addr"); + break; + + case OPCOMMA: + break; + + case OPMIN: + case OPMAX: + ptype = p->vtype; + break; + + default: + break; + } + +p->vtype = ptype; +return(p); +} + +#if SZINT < SZLONG +/* + for efficient subscripting, replace long ints by shorts + in easy places +*/ + +bigptr shorten(p) +register bigptr p; +{ +register bigptr q; + +if(p->vtype != TYLONG) + return(p); + +switch(p->tag) + { + case TERROR: + case TLIST: + return(p); + + case TCONST: + case TADDR: + return( mkconv(TYINT,p) ); + + case TEXPR: + break; + + default: + fatal1("shorten: invalid tag %d", p->tag); + } + +switch(p->opcode) + { + case OPPLUS: + case OPMINUS: + case OPSTAR: + q = shorten( cpexpr(p->rightp) ); + if(q->vtype == TYINT) + { + p->leftp = shorten(p->leftp); + if(p->leftp->vtype == TYLONG) + frexpr(q); + else + { + frexpr(p->rightp); + p->rightp = q; + p->vtype = TYINT; + } + } + break; + + case OPNEG: + p->leftp = shorten(p->leftp); + if(p->leftp->vtype == TYINT) + p->vtype = TYINT; + break; + + case OPCALL: + case OPCCALL: + p = mkconv(TYINT,p); + break; + default: + break; + } + +return(p); +} +#endif + +int +fixargs(doput, p0) +int doput; +struct bigblock *p0; +{ +register chainp p; +register bigptr q, t; +register int qtag; +int nargs; + +nargs = 0; +if(p0) + for(p = p0->b_list.listp ; p ; p = p->chain.nextp) + { + ++nargs; + q = p->chain.datap; + qtag = q->tag; + if(qtag == TCONST) + { + if(q->vtype == TYSHORT) + q = mkconv(tyint, q); + if(doput) + p->chain.datap = putconst(q); + else + p->chain.datap = q; + } + else if(qtag==TPRIM && q->b_prim.argsp==0 && q->b_prim.namep->vclass==CLPROC) + p->chain.datap = mkaddr(q->b_prim.namep); + else if(qtag==TPRIM && q->b_prim.argsp==0 && q->b_prim.namep->b_name.vdim!=NULL) + p->chain.datap = mkscalar(q->b_prim.namep); + else if(qtag==TPRIM && q->b_prim.argsp==0 && q->b_prim.namep->b_name.vdovar && + (t = memversion(q->b_prim.namep)) ) + p->chain.datap = fixtype(t); + else p->chain.datap = fixtype(q); + } +return(nargs); +} + +struct bigblock * +mkscalar(np) +register struct bigblock *np; +{ +register struct bigblock *ap; + +vardcl(np); +ap = mkaddr(np); + +#ifdef __vax__ + /* on the VAX, prolog causes array arguments + to point at the (0,...,0) element, except when + subscript checking is on + */ + if( !checksubs && np->vstg==STGARG) + { + register struct dimblock *dp; + dp = np->vdim; + frexpr(ap->memoffset); + ap->memoffset = mkexpr(OPSTAR, MKICON(typesize[np->vtype]), + cpexpr(dp->baseoffset) ); + } +#endif +return(ap); +} + + + + + +bigptr mkfunct(p) +register struct bigblock * p; +{ +chainp ep; +struct bigblock *ap; +struct extsym *extp; +register struct bigblock *np; +register struct bigblock *q; +int k, nargs; +int class; + +np = p->b_prim.namep; +class = np->vclass; + +if(class == CLUNKNOWN) + { + np->vclass = class = CLPROC; + if(np->vstg == STGUNKNOWN) + { + if((k = intrfunct(np->b_name.varname))) + { + np->vstg = STGINTR; + np->b_name.vardesc.varno = k; + np->b_name.vprocclass = PINTRINSIC; + } + else + { + extp = mkext( varunder(VL,np->b_name.varname) ); + extp->extstg = STGEXT; + np->vstg = STGEXT; + np->b_name.vardesc.varno = extp - extsymtab; + np->b_name.vprocclass = PEXTERNAL; + } + } + else if(np->vstg==STGARG) + { + if(np->vtype!=TYCHAR && !ftn66flag) + warn("Dummy procedure not declared EXTERNAL. Code may be wrong."); + np->b_name.vprocclass = PEXTERNAL; + } + } + +if(class != CLPROC) + fatal1("invalid class code for function", class); +if(p->b_prim.fcharp || p->b_prim.lcharp) + { + err("no substring of function call"); + goto error; + } +impldcl(np); +nargs = fixargs( np->b_name.vprocclass!=PINTRINSIC, p->b_prim.argsp); + +switch(np->b_name.vprocclass) + { + case PEXTERNAL: + ap = mkaddr(np); + call: + q = mkexpr(OPCALL, ap, p->b_prim.argsp); + q->vtype = np->vtype; + if(np->vleng) + q->vleng = cpexpr(np->vleng); + break; + + case PINTRINSIC: + q = intrcall(np, p->b_prim.argsp, nargs); + break; + + case PSTFUNCT: + q = stfcall(np, p->b_prim.argsp); + break; + + case PTHISPROC: + warn("recursive call"); + for(ep = entries ; ep ; ep = ep->entrypoint.nextp) + if(ep->entrypoint.enamep == np) + break; + if(ep == NULL) + fatal("mkfunct: impossible recursion"); + ap = builtin(np->vtype, varstr(XL, ep->entrypoint.entryname->extname) ); + goto call; + + default: + fatal1("mkfunct: impossible vprocclass %d", np->b_name.vprocclass); + q = 0; /* XXX gcc */ + } +ckfree(p); +return(q); + +error: + frexpr(p); + return( errnode() ); +} + + + +LOCAL struct bigblock * +stfcall(struct bigblock *np, struct bigblock *actlist) +{ + register chainp actuals; + int nargs; + chainp oactp, formals; + int type; + struct bigblock *q, *rhs; + bigptr ap; + register chainp rp; + chainp tlist; + + if(actlist) { + actuals = actlist->b_list.listp; + ckfree(actlist); + } else + actuals = NULL; + oactp = actuals; + + nargs = 0; + tlist = NULL; + type = np->vtype; + + formals = (chainp)np->b_name.vardesc.vstfdesc->chain.datap; + rhs = (bigptr)np->b_name.vardesc.vstfdesc->chain.nextp; + + /* copy actual arguments into temporaries */ + while(actuals!=NULL && formals!=NULL) { + rp = ALLOC(rplblock); + rp->rplblock.rplnp = q = formals->chain.datap; + ap = fixtype(actuals->chain.datap); + if(q->vtype==ap->vtype && q->vtype!=TYCHAR + && (ap->tag==TCONST || ap->tag==TADDR) ) { + rp->rplblock.rplvp = ap; + rp->rplblock.rplxp = NULL; + rp->rplblock.rpltag = ap->tag; + } else { + rp->rplblock.rplvp = fmktemp(q->vtype, q->vleng); + rp->rplblock.rplxp = fixtype( mkexpr(OPASSIGN, + cpexpr(rp->rplblock.rplvp), ap) ); + if( (rp->rplblock.rpltag = + rp->rplblock.rplxp->tag) == TERROR) + err("disagreement of argument types in statement function call"); + } + rp->rplblock.nextp = tlist; + tlist = rp; + actuals = actuals->chain.nextp; + formals = formals->chain.nextp; + ++nargs; + } + + if(actuals!=NULL || formals!=NULL) + err("statement function definition and argument list differ"); + + /* + now push down names involved in formal argument list, then + evaluate rhs of statement function definition in this environment + */ + rpllist = hookup(tlist, rpllist); + q = mkconv(type, fixtype(cpexpr(rhs)) ); + + /* now generate the tree ( t1=a1, (t2=a2,... , f))))) */ + while(--nargs >= 0) { + if(rpllist->rplblock.rplxp) + q = mkexpr(OPCOMMA, rpllist->rplblock.rplxp, q); + rp = rpllist->rplblock.nextp; + frexpr(rpllist->rplblock.rplvp); + ckfree(rpllist); + rpllist = rp; + } + + frchain( &oactp ); + return(q); +} + + + + +struct bigblock * +mklhs(struct bigblock *p) +{ + struct bigblock *s; + struct bigblock *np; + chainp rp; + int regn; + + /* first fixup name */ + + if(p->tag != TPRIM) + return(p); + + np = p->b_prim.namep; + + /* is name on the replace list? */ + + for(rp = rpllist ; rp ; rp = rp->rplblock.nextp) { + if(np == rp->rplblock.rplnp) { + if(rp->rplblock.rpltag == TNAME) { + np = p->b_prim.namep = rp->rplblock.rplvp; + break; + } else + return( cpexpr(rp->rplblock.rplvp) ); + } + } + + /* is variable a DO index in a register ? */ + + if(np->b_name.vdovar && ( (regn = inregister(np)) >= 0) ) { + if(np->vtype == TYERROR) + return( errnode() ); + else { + s = BALLO(); + s->tag = TADDR; + s->vstg = STGREG; + s->vtype = TYIREG; + s->b_addr.memno = regn; + s->b_addr.memoffset = MKICON(0); + return(s); + } + } + + vardcl(np); + s = mkaddr(np); + s->b_addr.memoffset = mkexpr(OPPLUS, s->b_addr.memoffset, suboffset(p) ); + frexpr(p->b_prim.argsp); + p->b_prim.argsp = NULL; + + /* now do substring part */ + + if(p->b_prim.fcharp || p->b_prim.lcharp) { + if(np->vtype != TYCHAR) + err1("substring of noncharacter %s", + varstr(VL,np->b_name.varname)); + else { + if(p->b_prim.lcharp == NULL) + p->b_prim.lcharp = cpexpr(s->vleng); + if(p->b_prim.fcharp) + s->vleng = mkexpr(OPMINUS, p->b_prim.lcharp, + mkexpr(OPMINUS, p->b_prim.fcharp, MKICON(1) )); + else { + frexpr(s->vleng); + s->vleng = p->b_prim.lcharp; + } + } + } + + s->vleng = fixtype( s->vleng ); + s->b_addr.memoffset = fixtype( s->b_addr.memoffset ); + ckfree(p); + return(s); +} + + + + +void +deregister(np) +struct bigblock *np; +{ +} + + + + +struct bigblock *memversion(np) +register struct bigblock *np; +{ +register struct bigblock *s; + +if(np->b_name.vdovar==NO || (inregister(np)<0) ) + return(NULL); +np->b_name.vdovar = NO; +s = mklhs( mkprim(np, 0,0,0) ); +np->b_name.vdovar = YES; +return(s); +} + + +int +inregister(np) +register struct bigblock *np; +{ +return(-1); +} + + + +int +enregister(np) +struct bigblock *np; +{ + return(NO); +} + + + + +bigptr suboffset(p) +register struct bigblock *p; +{ +int n; +bigptr size; +chainp cp; +bigptr offp, prod; +struct dimblock *dimp; +bigptr sub[8]; +register struct bigblock *np; + +np = p->b_prim.namep; +offp = MKICON(0); +n = 0; +if(p->b_prim.argsp) + for(cp = p->b_prim.argsp->b_list.listp ; cp ; cp = cp->chain.nextp) + { + sub[n++] = fixtype(cpexpr(cp->chain.datap)); + if(n > 7) + { + err("more than 7 subscripts"); + break; + } + } + +dimp = np->b_name.vdim; +if(n>0 && dimp==NULL) + err("subscripts on scalar variable"); +else if(dimp && dimp->ndim!=n) + err1("wrong number of subscripts on %s", + varstr(VL, np->b_name.varname) ); +else if(n > 0) + { + prod = sub[--n]; + while( --n >= 0) + prod = mkexpr(OPPLUS, sub[n], + mkexpr(OPSTAR, prod, cpexpr(dimp->dims[n].dimsize)) ); +#ifdef __vax__ + if(checksubs || np->vstg!=STGARG) + prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset)); +#else + prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset)); +#endif + if(checksubs) + prod = subcheck(np, prod); + if(np->vtype == TYCHAR) + size = cpexpr(np->vleng); + else size = MKICON( typesize[np->vtype] ); + prod = mkexpr(OPSTAR, prod, size); + offp = mkexpr(OPPLUS, offp, prod); + } + +if(p->b_prim.fcharp && np->vtype==TYCHAR) + offp = mkexpr(OPPLUS, offp, mkexpr(OPMINUS, cpexpr(p->b_prim.fcharp), MKICON(1) )); + +return(offp); +} + + +/* + * Check if an array is addressed out of bounds. + */ +bigptr +subcheck(struct bigblock *np, bigptr p) +{ + struct dimblock *dimp; + bigptr t, badcall; + int l1, l2; + + dimp = np->b_name.vdim; + if(dimp->nelt == NULL) + return(p); /* don't check arrays with * bounds */ + if( ISICON(p) ) { + if(p->b_const.fconst.ci < 0) + goto badsub; + if( ISICON(dimp->nelt) ) { + if(p->b_const.fconst.ci < dimp->nelt->b_const.fconst.ci) + return(p); + else + goto badsub; + } + } + + if (p->tag==TADDR && p->vstg==STGREG) { + t = p; + } else { + t = fmktemp(p->vtype, NULL); + putexpr(mkexpr(OPASSIGN, cpexpr(t), p)); + } + /* t now cotains evaluated expression */ + + l1 = newlabel(); + l2 = newlabel(); + putif(mkexpr(OPLT, cpexpr(t), cpexpr(dimp->nelt)), l1); + putif(mkexpr(OPGE, cpexpr(t), MKICON(0)), l1); + putgoto(l2); + putlabel(l1); + + badcall = call4(t->vtype, "s_rnge", mkstrcon(VL, np->b_name.varname), + mkconv(TYLONG, cpexpr(t)), + mkstrcon(XL, procname), MKICON(lineno)); + badcall->b_expr.opcode = OPCCALL; + + putexpr(badcall); + putlabel(l2); + return t; + +badsub: + frexpr(p); + err1("subscript on variable %s out of range", + varstr(VL,np->b_name.varname)); + return ( MKICON(0) ); +} + + + + +struct bigblock *mkaddr(p) +register struct bigblock *p; +{ +struct extsym *extp; +register struct bigblock *t; + +switch( p->vstg) + { + case STGUNKNOWN: + if(p->vclass != CLPROC) + break; + extp = mkext( varunder(VL, p->b_name.varname) ); + extp->extstg = STGEXT; + p->vstg = STGEXT; + p->b_name.vardesc.varno = extp - extsymtab; + p->b_name.vprocclass = PEXTERNAL; + + case STGCOMMON: + case STGEXT: + case STGBSS: + case STGINIT: + case STGEQUIV: + case STGARG: + case STGLENG: + case STGAUTO: + t = BALLO(); + t->tag = TADDR; + t->vclass = p->vclass; + t->vtype = p->vtype; + t->vstg = p->vstg; + t->b_addr.memno = p->b_name.vardesc.varno; + t->b_addr.memoffset = MKICON(p->b_name.voffset); + if(p->vleng) + t->vleng = cpexpr(p->vleng); + return(t); + + case STGINTR: + return( intraddr(p) ); + + } +/*debug*/ fprintf(diagfile, "mkaddr. vtype=%d, vclass=%d\n", p->vtype, p->vclass); +fatal1("mkaddr: impossible storage tag %d", p->vstg); +/* NOTREACHED */ +return 0; /* XXX gcc */ +} + + + +struct bigblock * +mkarg(type, argno) +int type, argno; +{ +register struct bigblock *p; + +p = BALLO(); +p->tag = TADDR; +p->vtype = type; +p->vclass = CLVAR; +p->vstg = (type==TYLENG ? STGLENG : STGARG); +p->b_addr.memno = argno; +return(p); +} + + + + +bigptr mkprim(v, args, lstr, rstr) +register bigptr v; +struct bigblock *args; +bigptr lstr, rstr; +{ +register struct bigblock *p; + +if(v->vclass == CLPARAM) + { + if(args || lstr || rstr) + { + err1("no qualifiers on parameter name", varstr(VL,v->b_name.varname)); + frexpr(args); + frexpr(lstr); + frexpr(rstr); + frexpr(v); + return( errnode() ); + } + return( cpexpr(v->b_param.paramval) ); + } + +p = BALLO(); +p->tag = TPRIM; +p->vtype = v->vtype; +p->b_prim.namep = v; +p->b_prim.argsp = args; +p->b_prim.fcharp = lstr; +p->b_prim.lcharp = rstr; +return(p); +} + + +void +vardcl(v) +register struct bigblock *v; +{ +int nelt; +struct dimblock *t; +struct bigblock *p; +bigptr neltp; + +if(v->b_name.vdcldone) return; + +if(v->vtype == TYUNKNOWN) + impldcl(v); +if(v->vclass == CLUNKNOWN) + v->vclass = CLVAR; +else if(v->vclass!=CLVAR && v->b_name.vprocclass!=PTHISPROC) + { + dclerr("used as variable", v); + return; + } +if(v->vstg==STGUNKNOWN) + v->vstg = implstg[ letter(v->b_name.varname[0]) ]; + +switch(v->vstg) + { + case STGBSS: + v->b_name.vardesc.varno = ++lastvarno; + break; + case STGAUTO: + if(v->vclass==CLPROC && v->b_name.vprocclass==PTHISPROC) + break; + nelt = 1; + if((t = v->b_name.vdim)) { + if( (neltp = t->nelt) && ISCONST(neltp) ) + nelt = neltp->b_const.fconst.ci; + else + dclerr("adjustable automatic array", v); + } + p = autovar(nelt, v->vtype, v->vleng); + v->b_name.voffset = p->b_addr.memoffset->b_const.fconst.ci; + frexpr(p); + break; + + default: + break; + } +v->b_name.vdcldone = YES; +} + + + +void +impldcl(p) +register struct bigblock *p; +{ +register int k; +int type, leng; + +if(p->b_name.vdcldone || (p->vclass==CLPROC && p->b_name.vprocclass==PINTRINSIC) ) + return; +if(p->vtype == TYUNKNOWN) + { + k = letter(p->b_name.varname[0]); + type = impltype[ k ]; + leng = implleng[ k ]; + if(type == TYUNKNOWN) + { + if(p->vclass == CLPROC) + return; + dclerr("attempt to use undefined variable", p); + type = TYERROR; + leng = 1; + } + settype(p, type, leng); + } +} + + + + +LOCAL int +letter(c) +register int c; +{ +if( isupper(c) ) + c = tolower(c); +return(c - 'a'); +} + +#define ICONEQ(z, c) (ISICON(z) && z->b_const.fconst.ci==c) +#define COMMUTE { e = lp; lp = rp; rp = e; } + + +struct bigblock * +mkexpr(opcode, lp, rp) +int opcode; +register bigptr lp, rp; +{ +register struct bigblock *e, *e1; +int etype; +int ltype, rtype; +int ltag, rtag; + +ltype = lp->vtype; +ltag = lp->tag; +if(rp && opcode!=OPCALL && opcode!=OPCCALL) + { + rtype = rp->vtype; + rtag = rp->tag; + } +else rtype = rtag = 0; + +etype = cktype(opcode, ltype, rtype); +if(etype == TYERROR) + goto error; + +switch(opcode) + { + /* check for multiplication by 0 and 1 and addition to 0 */ + + case OPSTAR: + if( ISCONST(lp) ) + COMMUTE + + if( ISICON(rp) ) + { + if(rp->b_const.fconst.ci == 0) + goto retright; + goto mulop; + } + break; + + case OPSLASH: + case OPMOD: + if( ICONEQ(rp, 0) ) + { + err("attempted division by zero"); + rp = MKICON(1); + break; + } + if(opcode == OPMOD) + break; + + + mulop: + if( ISICON(rp) ) + { + if(rp->b_const.fconst.ci == 1) + goto retleft; + + if(rp->b_const.fconst.ci == -1) + { + frexpr(rp); + return( mkexpr(OPNEG, lp, 0) ); + } + } + + if( ISSTAROP(lp) && ISICON(lp->b_expr.rightp) ) + { + if(opcode == OPSTAR) + e = mkexpr(OPSTAR, lp->b_expr.rightp, rp); + else if(ISICON(rp) && lp->b_expr.rightp->b_const.fconst.ci % rp->b_const.fconst.ci == 0) + e = mkexpr(OPSLASH, lp->b_expr.rightp, rp); + else break; + + e1 = lp->b_expr.leftp; + ckfree(lp); + return( mkexpr(OPSTAR, e1, e) ); + } + break; + + + case OPPLUS: + if( ISCONST(lp) ) + COMMUTE + goto addop; + + case OPMINUS: + if( ICONEQ(lp, 0) ) + { + frexpr(lp); + return( mkexpr(OPNEG, rp, 0) ); + } + + if( ISCONST(rp) ) + { + opcode = OPPLUS; + consnegop(rp); + } + + addop: + if( ISICON(rp) ) + { + if(rp->b_const.fconst.ci == 0) + goto retleft; + if( ISPLUSOP(lp) && ISICON(lp->b_expr.rightp) ) + { + e = mkexpr(OPPLUS, lp->b_expr.rightp, rp); + e1 = lp->b_expr.leftp; + ckfree(lp); + return( mkexpr(OPPLUS, e1, e) ); + } + } + break; + + + case OPPOWER: + break; + + case OPNEG: + if(ltag==TEXPR && lp->b_expr.opcode==OPNEG) + { + e = lp->b_expr.leftp; + ckfree(lp); + return(e); + } + break; + + case OPNOT: + if(ltag==TEXPR && lp->b_expr.opcode==OPNOT) + { + e = lp->b_expr.leftp; + ckfree(lp); + return(e); + } + break; + + case OPCALL: + case OPCCALL: + etype = ltype; + if(rp!=NULL && rp->b_list.listp==NULL) + { + ckfree(rp); + rp = NULL; + } + break; + + case OPAND: + case OPOR: + if( ISCONST(lp) ) + COMMUTE + + if( ISCONST(rp) ) + { + if(rp->b_const.fconst.ci == 0) + if(opcode == OPOR) + goto retleft; + else + goto retright; + else if(opcode == OPOR) + goto retright; + else + goto retleft; + } + case OPEQV: + case OPNEQV: + + case OPBITAND: + case OPBITOR: + case OPBITXOR: + case OPBITNOT: + case OPLSHIFT: + case OPRSHIFT: + + case OPLT: + case OPGT: + case OPLE: + case OPGE: + case OPEQ: + case OPNE: + + case OPCONCAT: + break; + case OPMIN: + case OPMAX: + + case OPASSIGN: + + case OPCONV: + case OPADDR: + + case OPCOMMA: + break; + + default: + fatal1("mkexpr: impossible opcode %d", opcode); + } + +e = BALLO(); +e->tag = TEXPR; +e->b_expr.opcode = opcode; +e->vtype = etype; +e->b_expr.leftp = lp; +e->b_expr.rightp = rp; +if(ltag==TCONST && (rp==0 || rtag==TCONST) ) + e = fold(e); +return(e); + +retleft: + frexpr(rp); + return(lp); + +retright: + frexpr(lp); + return(rp); + +error: + frexpr(lp); + if(rp && opcode!=OPCALL && opcode!=OPCCALL) + frexpr(rp); + return( errnode() ); +} + +#define ERR(s) { errs = s; goto error; } + +int +cktype(op, lt, rt) +register int op, lt, rt; +{ +char *errs = NULL; /* XXX gcc */ + +if(lt==TYERROR || rt==TYERROR) + goto error1; + +if(lt==TYUNKNOWN) + return(TYUNKNOWN); +if(rt==TYUNKNOWN) + if(op!=OPNOT && op!=OPBITNOT && op!=OPNEG && op!=OPCALL && op!=OPCCALL && op!=OPADDR) + return(TYUNKNOWN); + +switch(op) + { + case OPPLUS: + case OPMINUS: + case OPSTAR: + case OPSLASH: + case OPPOWER: + case OPMOD: + if( ISNUMERIC(lt) && ISNUMERIC(rt) ) + return( maxtype(lt, rt) ); + ERR("nonarithmetic operand of arithmetic operator") + + case OPNEG: + if( ISNUMERIC(lt) ) + return(lt); + ERR("nonarithmetic operand of negation") + + case OPNOT: + if(lt == TYLOGICAL) + return(TYLOGICAL); + ERR("NOT of nonlogical") + + case OPAND: + case OPOR: + case OPEQV: + case OPNEQV: + if(lt==TYLOGICAL && rt==TYLOGICAL) + return(TYLOGICAL); + ERR("nonlogical operand of logical operator") + + case OPLT: + case OPGT: + case OPLE: + case OPGE: + case OPEQ: + case OPNE: + if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL) + { + if(lt != rt) + ERR("illegal comparison") + } + + else if( ISCOMPLEX(lt) || ISCOMPLEX(rt) ) + { + if(op!=OPEQ && op!=OPNE) + ERR("order comparison of complex data") + } + + else if( ! ISNUMERIC(lt) || ! ISNUMERIC(rt) ) + ERR("comparison of nonarithmetic data") + return(TYLOGICAL); + + case OPCONCAT: + if(lt==TYCHAR && rt==TYCHAR) + return(TYCHAR); + ERR("concatenation of nonchar data") + + case OPCALL: + case OPCCALL: + return(lt); + + case OPADDR: + return(TYADDR); + + case OPCONV: + if(rt == 0) + return(0); + case OPASSIGN: + if( ISINT(lt) && rt==TYCHAR) + return(lt); + if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL) + if(op!=OPASSIGN || lt!=rt) + { +/* debug fprintf(diagfile, " lt=%d, rt=%d, op=%d\n", lt, rt, op); */ +/* debug fatal("impossible conversion. possible compiler bug"); */ + ERR("impossible conversion") + } + return(lt); + + case OPMIN: + case OPMAX: + case OPBITOR: + case OPBITAND: + case OPBITXOR: + case OPBITNOT: + case OPLSHIFT: + case OPRSHIFT: + return(lt); + + case OPCOMMA: + return(rt); + + default: + fatal1("cktype: impossible opcode %d", op); + } +error: err(errs); +error1: return(TYERROR); +} + +LOCAL bigptr fold(e) +register struct bigblock *e; +{ +struct bigblock *p; +register bigptr lp, rp; +int etype, mtype, ltype, rtype, opcode; +int i, ll, lr; +char *q, *s; +union constant lcon, rcon; + +opcode = e->b_expr.opcode; +etype = e->vtype; + +lp = e->b_expr.leftp; +ltype = lp->vtype; +rp = e->b_expr.rightp; + +if(rp == 0) + switch(opcode) + { + case OPNOT: + lp->b_const.fconst.ci = ! lp->b_const.fconst.ci; + return(lp); + + case OPBITNOT: + lp->b_const.fconst.ci = ~ lp->b_const.fconst.ci; + return(lp); + + case OPNEG: + consnegop(lp); + return(lp); + + case OPCONV: + case OPADDR: + return(e); + + default: + fatal1("fold: invalid unary operator %d", opcode); + } + +rtype = rp->vtype; + +p = BALLO(); +p->tag = TCONST; +p->vtype = etype; +p->vleng = e->vleng; + +switch(opcode) + { + case OPCOMMA: + return(e); + + case OPAND: + p->b_const.fconst.ci = lp->b_const.fconst.ci && rp->b_const.fconst.ci; + break; + + case OPOR: + p->b_const.fconst.ci = lp->b_const.fconst.ci || rp->b_const.fconst.ci; + break; + + case OPEQV: + p->b_const.fconst.ci = lp->b_const.fconst.ci == rp->b_const.fconst.ci; + break; + + case OPNEQV: + p->b_const.fconst.ci = lp->b_const.fconst.ci != rp->b_const.fconst.ci; + break; + + case OPBITAND: + p->b_const.fconst.ci = lp->b_const.fconst.ci & rp->b_const.fconst.ci; + break; + + case OPBITOR: + p->b_const.fconst.ci = lp->b_const.fconst.ci | rp->b_const.fconst.ci; + break; + + case OPBITXOR: + p->b_const.fconst.ci = lp->b_const.fconst.ci ^ rp->b_const.fconst.ci; + break; + + case OPLSHIFT: + p->b_const.fconst.ci = lp->b_const.fconst.ci << rp->b_const.fconst.ci; + break; + + case OPRSHIFT: + p->b_const.fconst.ci = lp->b_const.fconst.ci >> rp->b_const.fconst.ci; + break; + + case OPCONCAT: + ll = lp->vleng->b_const.fconst.ci; + lr = rp->vleng->b_const.fconst.ci; + p->b_const.fconst.ccp = q = (char *) ckalloc(ll+lr); + p->vleng = MKICON(ll+lr); + s = lp->b_const.fconst.ccp; + for(i = 0 ; i < ll ; ++i) + *q++ = *s++; + s = rp->b_const.fconst.ccp; + for(i = 0; i < lr; ++i) + *q++ = *s++; + break; + + + case OPPOWER: + if( ! ISINT(rtype) ) + return(e); + conspower(&(p->b_const.fconst), lp, rp->b_const.fconst.ci); + break; + + + default: + if(ltype == TYCHAR) + { + lcon.ci = cmpstr(lp->b_const.fconst.ccp, rp->b_const.fconst.ccp, + lp->vleng->b_const.fconst.ci, rp->vleng->b_const.fconst.ci); + rcon.ci = 0; + mtype = tyint; + } + else { + mtype = maxtype(ltype, rtype); + consconv(mtype, &lcon, ltype, &(lp->b_const.fconst) ); + consconv(mtype, &rcon, rtype, &(rp->b_const.fconst) ); + } + consbinop(opcode, mtype, &(p->b_const.fconst), &lcon, &rcon); + break; + } + +frexpr(e); +return(p); +} + + + +/* assign constant l = r , doing coercion */ +void +consconv(lt, lv, rt, rv) +int lt, rt; +register union constant *lv, *rv; +{ +switch(lt) + { + case TYSHORT: + case TYLONG: + if( ISINT(rt) ) + lv->ci = rv->ci; + else lv->ci = rv->cd[0]; + break; + + case TYCOMPLEX: + case TYDCOMPLEX: + switch(rt) + { + case TYSHORT: + case TYLONG: + /* fall through and do real assignment of + first element + */ + case TYREAL: + case TYDREAL: + lv->cd[1] = 0; break; + case TYCOMPLEX: + case TYDCOMPLEX: + lv->cd[1] = rv->cd[1]; break; + } + + case TYREAL: + case TYDREAL: + if( ISINT(rt) ) + lv->cd[0] = rv->ci; + else lv->cd[0] = rv->cd[0]; + break; + + case TYLOGICAL: + lv->ci = rv->ci; + break; + } +} + + +void +consnegop(p) +register struct bigblock *p; +{ +switch(p->vtype) + { + case TYSHORT: + case TYLONG: + p->b_const.fconst.ci = - p->b_const.fconst.ci; + break; + + case TYCOMPLEX: + case TYDCOMPLEX: + p->b_const.fconst.cd[1] = - p->b_const.fconst.cd[1]; + /* fall through and do the real parts */ + case TYREAL: + case TYDREAL: + p->b_const.fconst.cd[0] = - p->b_const.fconst.cd[0]; + break; + default: + fatal1("consnegop: impossible type %d", p->vtype); + } +} + + + +LOCAL void +conspower(powp, ap, n) +register union constant *powp; +struct bigblock *ap; +ftnint n; +{ +register int type; +union constant x; + +switch(type = ap->vtype) /* pow = 1 */ + { + case TYSHORT: + case TYLONG: + powp->ci = 1; + break; + case TYCOMPLEX: + case TYDCOMPLEX: + powp->cd[1] = 0; + case TYREAL: + case TYDREAL: + powp->cd[0] = 1; + break; + default: + fatal1("conspower: invalid type %d", type); + } + +if(n == 0) + return; +if(n < 0) + { + if( ISINT(type) ) + { + err("integer ** negative power "); + return; + } + n = - n; + consbinop(OPSLASH, type, &x, powp, &(ap->b_const.fconst)); + } +else + consbinop(OPSTAR, type, &x, powp, &(ap->b_const.fconst)); + +for( ; ; ) + { + if(n & 01) + consbinop(OPSTAR, type, powp, powp, &x); + if(n >>= 1) + consbinop(OPSTAR, type, &x, &x, &x); + else + break; + } +} + + + +/* do constant operation cp = a op b */ + + +LOCAL void +consbinop(opcode, type, cp, ap, bp) +int opcode, type; +register union constant *ap, *bp, *cp; +{ +int k; +double temp; + +switch(opcode) + { + case OPPLUS: + switch(type) + { + case TYSHORT: + case TYLONG: + cp->ci = ap->ci + bp->ci; + break; + case TYCOMPLEX: + case TYDCOMPLEX: + cp->cd[1] = ap->cd[1] + bp->cd[1]; + case TYREAL: + case TYDREAL: + cp->cd[0] = ap->cd[0] + bp->cd[0]; + break; + } + break; + + case OPMINUS: + switch(type) + { + case TYSHORT: + case TYLONG: + cp->ci = ap->ci - bp->ci; + break; + case TYCOMPLEX: + case TYDCOMPLEX: + cp->cd[1] = ap->cd[1] - bp->cd[1]; + case TYREAL: + case TYDREAL: + cp->cd[0] = ap->cd[0] - bp->cd[0]; + break; + } + break; + + case OPSTAR: + switch(type) + { + case TYSHORT: + case TYLONG: + cp->ci = ap->ci * bp->ci; + break; + case TYREAL: + case TYDREAL: + cp->cd[0] = ap->cd[0] * bp->cd[0]; + break; + case TYCOMPLEX: + case TYDCOMPLEX: + temp = ap->cd[0] * bp->cd[0] - + ap->cd[1] * bp->cd[1] ; + cp->cd[1] = ap->cd[0] * bp->cd[1] + + ap->cd[1] * bp->cd[0] ; + cp->cd[0] = temp; + break; + } + break; + case OPSLASH: + switch(type) + { + case TYSHORT: + case TYLONG: + cp->ci = ap->ci / bp->ci; + break; + case TYREAL: + case TYDREAL: + cp->cd[0] = ap->cd[0] / bp->cd[0]; + break; + case TYCOMPLEX: + case TYDCOMPLEX: + zdiv(&cp->dc, &ap->dc, &bp->dc); + break; + } + break; + + case OPMOD: + if( ISINT(type) ) + { + cp->ci = ap->ci % bp->ci; + break; + } + else + fatal("inline mod of noninteger"); + + default: /* relational ops */ + switch(type) + { + case TYSHORT: + case TYLONG: + if(ap->ci < bp->ci) + k = -1; + else if(ap->ci == bp->ci) + k = 0; + else k = 1; + break; + case TYREAL: + case TYDREAL: + if(ap->cd[0] < bp->cd[0]) + k = -1; + else if(ap->cd[0] == bp->cd[0]) + k = 0; + else k = 1; + break; + case TYCOMPLEX: + case TYDCOMPLEX: + if(ap->cd[0] == bp->cd[0] && + ap->cd[1] == bp->cd[1] ) + k = 0; + else k = 1; + break; + default: /* XXX gcc */ + k = 0; + break; + } + + switch(opcode) + { + case OPEQ: + cp->ci = (k == 0); + break; + case OPNE: + cp->ci = (k != 0); + break; + case OPGT: + cp->ci = (k == 1); + break; + case OPLT: + cp->ci = (k == -1); + break; + case OPGE: + cp->ci = (k >= 0); + break; + case OPLE: + cp->ci = (k <= 0); + break; + } + break; + } +} + + + +int +conssgn(p) +register bigptr p; +{ +if( ! ISCONST(p) ) + fatal( "sgn(nonconstant)" ); + +switch(p->vtype) + { + case TYSHORT: + case TYLONG: + if(p->b_const.fconst.ci > 0) return(1); + if(p->b_const.fconst.ci < 0) return(-1); + return(0); + + case TYREAL: + case TYDREAL: + if(p->b_const.fconst.cd[0] > 0) return(1); + if(p->b_const.fconst.cd[0] < 0) return(-1); + return(0); + + case TYCOMPLEX: + case TYDCOMPLEX: + return(p->b_const.fconst.cd[0]!=0 || p->b_const.fconst.cd[1]!=0); + + default: + fatal1( "conssgn(type %d)", p->vtype); + } +/* NOTREACHED */ +return 0; /* XXX gcc */ +} + +char *powint[ ] = { "pow_ii", "pow_ri", "pow_di", "pow_ci", "pow_zi" }; + + +LOCAL bigptr mkpower(p) +register struct bigblock *p; +{ +register bigptr q, lp, rp; +int ltype, rtype, mtype; + +lp = p->b_expr.leftp; +rp = p->b_expr.rightp; +ltype = lp->vtype; +rtype = rp->vtype; + +if(ISICON(rp)) + { + if(rp->b_const.fconst.ci == 0) + { + frexpr(p); + if( ISINT(ltype) ) + return( MKICON(1) ); + else + return( putconst( mkconv(ltype, MKICON(1))) ); + } + if(rp->b_const.fconst.ci < 0) + { + if( ISINT(ltype) ) + { + frexpr(p); + err("integer**negative"); + return( errnode() ); + } + rp->b_const.fconst.ci = - rp->b_const.fconst.ci; + p->b_expr.leftp = lp = fixexpr(mkexpr(OPSLASH, MKICON(1), lp)); + } + if(rp->b_const.fconst.ci == 1) + { + frexpr(rp); + ckfree(p); + return(lp); + } + + if( ONEOF(ltype, MSKINT|MSKREAL) ) + { + p->vtype = ltype; + return(p); + } + } +if( ISINT(rtype) ) + { + if(ltype==TYSHORT && rtype==TYSHORT) + q = call2(TYSHORT, "pow_hh", lp, rp); + else { + if(ltype == TYSHORT) + { + ltype = TYLONG; + lp = mkconv(TYLONG,lp); + } + q = call2(ltype, powint[ltype-TYLONG], lp, mkconv(TYLONG, rp)); + } + } +else if( ISREAL( (mtype = maxtype(ltype,rtype)) )) + q = call2(mtype, "pow_dd", + mkconv(TYDREAL,lp), mkconv(TYDREAL,rp)); +else { + q = call2(TYDCOMPLEX, "pow_zz", + mkconv(TYDCOMPLEX,lp), mkconv(TYDCOMPLEX,rp)); + if(mtype == TYCOMPLEX) + q = mkconv(TYCOMPLEX, q); + } +ckfree(p); +return(q); +} + + + +/* Complex Division. Same code as in Runtime Library +*/ + + + +LOCAL void +zdiv(c, a, b) +register struct dcomplex *a, *b, *c; +{ +double ratio, den; +double abr, abi; + +if( (abr = b->dreal) < 0.) + abr = - abr; +if( (abi = b->dimag) < 0.) + abi = - abi; +if( abr <= abi ) + { + if(abi == 0) + fatal("complex division by zero"); + ratio = b->dreal / b->dimag ; + den = b->dimag * (1 + ratio*ratio); + c->dreal = (a->dreal*ratio + a->dimag) / den; + c->dimag = (a->dimag*ratio - a->dreal) / den; + } + +else + { + ratio = b->dimag / b->dreal ; + den = b->dreal * (1 + ratio*ratio); + c->dreal = (a->dreal + a->dimag*ratio) / den; + c->dimag = (a->dimag - a->dreal*ratio) / den; + } + +} diff --git a/compilers/pcc/pcc-1.0.0/f77/fcom/ftypes.h b/compilers/pcc/pcc-1.0.0/f77/fcom/ftypes.h new file mode 100644 index 00000000..81468abc --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/fcom/ftypes.h @@ -0,0 +1,82 @@ +/* $Id: ftypes.h,v 1.5 2008/12/19 08:08:48 ragge Exp $ */ +/* + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code and documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditionsand the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed or owned by Caldera + * International, Inc. + * Neither the name of Caldera International, Inc. nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* variable types + * numeric assumptions: + * int < reals < complexes + * TYDREAL-TYREAL = TYDCOMPLEX-TYCOMPLEX + */ + +#ifndef _FTYPES_H_ +#define _FTYPES_H_ + + +#define TYUNKNOWN 0 +#define TYADDR 1 +#define TYSHORT 2 +#define TYLONG 3 +#define TYREAL 4 +#define TYDREAL 5 +#define TYCOMPLEX 6 +#define TYDCOMPLEX 7 +#define TYLOGICAL 8 +#define TYCHAR 9 +#define TYSUBR 10 +#define TYERROR 11 + +#define NTYPES (TYERROR+1) + +/* + * Type conversion from pcc to f77 internal format. + */ +#define FSZADDR (SZPOINT(0)/SZCHAR) /* XXX - typecheck? */ +#define FSZSHORT (SZSHORT/SZCHAR) +#define FSZINT (SZINT/SZCHAR) +#define FSZLONG (SZLONG/SZCHAR) +#define ALIADDR (ALPOINT/ALCHAR) +#define ALISHORT (ALSHORT/ALCHAR) +#define ALILONG (ALLONG/ALCHAR) +#define ALIDOUBLE (ALDOUBLE/ALCHAR) + +#ifndef SZINT +#include "macdefs.h" +#endif +#if SZINT == SZSHORT +#define TYINT TYSHORT +#else /* SZLONG >= SZINT */ +#define TYINT TYLONG +#endif + +#define TYLENG TYLONG +#endif /* !_FTYPES_H_ */ diff --git a/compilers/pcc/pcc-1.0.0/f77/fcom/gram.dcl b/compilers/pcc/pcc-1.0.0/f77/fcom/gram.dcl new file mode 100644 index 00000000..493f7a96 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/fcom/gram.dcl @@ -0,0 +1,318 @@ +spec: dcl + | common + | external + | intrinsic + | equivalence + | data + | implicit + | SSAVE + { saveall = YES; } + | SSAVE savelist + | SFORMAT + { fmtstmt(thislabel); setfmt(thislabel); } + | SPARAM in_dcl SLPAR paramlist SRPAR + ; + +dcl: type name in_dcl dims lengspec + { settype($2, $1, $5); + if(ndim>0) setbound($2,ndim,dims); + } + | dcl SCOMMA name dims lengspec + { settype($3, $1, $5); + if(ndim>0) setbound($3,ndim,dims); + } + ; + +type: typespec lengspec + { varleng = $2; } + ; + +typespec: typename + { varleng = ($1<0 || $1==TYLONG ? 0 : typesize[$1]); } + ; + +typename: SINTEGER { $$ = TYLONG; } + | SREAL { $$ = TYREAL; } + | SCOMPLEX { $$ = TYCOMPLEX; } + | SDOUBLE { $$ = TYDREAL; } + | SDCOMPLEX { $$ = TYDCOMPLEX; } + | SLOGICAL { $$ = TYLOGICAL; } + | SCHARACTER { $$ = TYCHAR; } + | SUNDEFINED { $$ = TYUNKNOWN; } + | SDIMENSION { $$ = TYUNKNOWN; } + | SAUTOMATIC { $$ = - STGAUTO; } + | SSTATIC { $$ = - STGBSS; } + ; + +lengspec: + { $$ = varleng; } + | SSTAR expr + { + if( ! ISICON($2) ) + { + $$ = 0; + dclerr("length must be an integer constant", 0); + } + else $$ = $2->b_const.fconst.ci; + } + | SSTAR SLPAR SSTAR SRPAR + { $$ = 0; } + ; + +common: SCOMMON in_dcl var + { incomm( $$ = comblock(0, 0) , $3 ); } + | SCOMMON in_dcl comblock var + { $$ = $3; incomm($3, $4); } + | common opt_comma comblock opt_comma var + { $$ = $3; incomm($3, $5); } + | common SCOMMA var + { incomm($1, $3); } + ; + +comblock: SCONCAT + { $$ = comblock(0, 0); } + | SSLASH SFNAME SSLASH + { $$ = comblock(toklen, token); } + ; + +external: SEXTERNAL in_dcl name + { setext($3); } + | external SCOMMA name + { setext($3); } + ; + +intrinsic: SINTRINSIC in_dcl name + { setintr($3); } + | intrinsic SCOMMA name + { setintr($3); } + ; + +equivalence: SEQUIV in_dcl equivset + | equivalence SCOMMA equivset + ; + +equivset: SLPAR equivlist SRPAR + { + struct equivblock *p; + if(nequiv >= MAXEQUIV) + fatal("too many equivalences"); + p = & eqvclass[nequiv++]; + p->eqvinit = 0; + p->eqvbottom = 0; + p->eqvtop = 0; + p->equivs = $2; + } + ; + +equivlist: lhs + { $$ = ALLOC(eqvchain); $$->eqvchain.eqvitem = $1; } + | equivlist SCOMMA lhs + { $$ = ALLOC(eqvchain); $$->eqvchain.eqvitem = $3; $$->eqvchain.nextp = $1; } + ; + +data: SDATA in_data datalist + | data opt_comma datalist + ; + +in_data: + { if(parstate == OUTSIDE) + { + newproc(); + startproc(0, CLMAIN); + } + if(parstate < INDATA) + { + enddcl(); + parstate = INDATA; + } + } + ; + +datalist: datavarlist SSLASH vallist SSLASH + { ftnint junk; + if(nextdata(&junk,&junk) != NULL) + { + err("too few initializers"); + curdtp = NULL; + } + frdata($1); + frrpl(); + } + ; + +vallist: { toomanyinit = NO; } val + | vallist SCOMMA val + ; + +val: value + { dataval(NULL, $1); } + | simple SSTAR value + { dataval($1, $3); } + ; + +value: simple + | addop simple + { if( $1==OPMINUS && ISCONST($2) ) + consnegop($2); + $$ = $2; + } + | complex_const + | bit_const + ; + +savelist: saveitem + | savelist SCOMMA saveitem + ; + +saveitem: name + { int k; + $1->b_name.vsave = 1; + k = $1->vstg; + if( ! ONEOF(k, M(STGUNKNOWN)|M(STGBSS)|M(STGINIT)) ) + dclerr("can only save static variables", $1); + } + | comblock + { $1->extsave = 1; } + ; + +paramlist: paramitem + | paramlist SCOMMA paramitem + ; + +paramitem: name SEQUALS expr + { if($1->vclass == CLUNKNOWN) + { $1->vclass = CLPARAM; + $1->b_param.paramval = $3; + } + else dclerr("cannot make %s parameter", $1); + } + ; + +var: name dims + { if(ndim>0) setbound($1, ndim, dims); } + ; + +datavar: lhs + { struct bigblock *np; + vardcl(np = $1->b_prim.namep); + if(np->vstg == STGBSS) + np->vstg = STGINIT; + else if(np->vstg == STGCOMMON) + extsymtab[np->b_name.vardesc.varno].extinit = YES; + else if(np->vstg==STGEQUIV) + eqvclass[np->b_name.vardesc.varno].eqvinit = YES; + else if(np->vstg != STGINIT) + dclerr("inconsistent storage classes", np); + $$ = mkchain($1, 0); + } + | SLPAR datavarlist SCOMMA dospec SRPAR + { chainp p; struct bigblock *q; + q = BALLO(); + q->tag = TIMPLDO; + q->b_impldo.varnp = $4->chain.datap; + p = $4->chain.nextp; + if(p) { q->b_impldo.implb = p->chain.datap; p = p->chain.nextp; } + if(p) { q->b_impldo.impub = p->chain.datap; p = p->chain.nextp; } + if(p) { q->b_impldo.impstep = p->chain.datap; p = p->chain.nextp; } + frchain( & ($4) ); + $$ = mkchain(q, 0); + q->b_impldo.datalist = hookup($2, $$); + } + ; + +datavarlist: datavar + { curdtp = $1; curdtelt = 0; } + | datavarlist SCOMMA datavar + { $$ = hookup($1, $3); } + ; + +dims: + { ndim = 0; } + | SLPAR dimlist SRPAR + ; + +dimlist: { ndim = 0; } dim + | dimlist SCOMMA dim + ; + +dim: ubound + { dims[ndim].lb = 0; + dims[ndim].ub = $1; + ++ndim; + } + | expr SCOLON ubound + { dims[ndim].lb = $1; + dims[ndim].ub = $3; + ++ndim; + } + ; + +ubound: SSTAR + { $$ = 0; } + | expr + ; + +labellist: label + { nstars = 1; labarray[0] = $1; } + | labellist SCOMMA label + { labarray[nstars++] = $3; } + ; + +label: labelval + { if($1->labinacc) + warn1("illegal branch to inner block, statement %s", + convic( (ftnint) ($1->stateno) )); + else if($1->labdefined == NO) + $1->blklevel = blklevel; + $1->labused = YES; + } + ; + +labelval: SICON + { $$ = mklabel( convci(toklen, token) ); } + ; + +implicit: SIMPLICIT in_dcl implist + | implicit SCOMMA implist + ; + +implist: imptype SLPAR letgroups SRPAR + ; + +imptype: { needkwd = 1; } type + { vartype = $2; } + ; + +letgroups: letgroup + | letgroups SCOMMA letgroup + ; + +letgroup: letter + { setimpl(vartype, varleng, $1, $1); } + | letter SMINUS letter + { setimpl(vartype, varleng, $1, $3); } + ; + +letter: SFNAME + { if(toklen!=1 || token[0]<'a' || token[0]>'z') + { + dclerr("implicit item must be single letter", 0); + $$ = 0; + } + else $$ = token[0]; + } + ; + +in_dcl: + { switch(parstate) + { + case OUTSIDE: newproc(); + startproc(0, CLMAIN); + case INSIDE: parstate = INDCL; + case INDCL: break; + + default: + dclerr("declaration among executables", 0); + } + } + ; diff --git a/compilers/pcc/pcc-1.0.0/f77/fcom/gram.exec b/compilers/pcc/pcc-1.0.0/f77/fcom/gram.exec new file mode 100644 index 00000000..546f4b96 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/fcom/gram.exec @@ -0,0 +1,112 @@ +exec: iffable + | SDO end_spec label opt_comma dospec + { + if($3->labdefined) + execerr("no backward DO loops"); + $3->blklevel = blklevel+1; + exdo($3->labelno, $5); + } + | logif iffable + { exendif(); thiswasbranch = NO; } + | logif STHEN + | SELSEIF end_spec SLPAR expr SRPAR STHEN + { exelif($4); lastwasbranch = NO; } + | SELSE end_spec + { exelse(); lastwasbranch = NO; } + | SENDIF end_spec + { exendif(); lastwasbranch = NO; } + ; + +logif: SLOGIF end_spec SLPAR expr SRPAR + { exif($4); } + ; + +dospec: name SEQUALS exprlist + { $$ = mkchain($1, $3); } + ; + +iffable: let lhs SEQUALS expr + { exequals($2, $4); } + | SASSIGN end_spec labelval STO name + { exassign($5, $3); } + | SCONTINUE end_spec + | goto + | io + { inioctl = NO; } + | SARITHIF end_spec SLPAR expr SRPAR label SCOMMA label SCOMMA label + { exarif($4, $6, $8, $10); thiswasbranch = YES; } + | call + { excall($1, 0, 0, labarray); } + | call SLPAR SRPAR + { excall($1, 0, 0, labarray); } + | call SLPAR callarglist SRPAR + { excall($1, mklist($3), nstars, labarray); } + | SRETURN end_spec opt_expr + { exreturn($3); thiswasbranch = YES; } + | stop end_spec opt_expr + { exstop($1, $3); thiswasbranch = $1; } + ; + +let: SLET + { if(parstate == OUTSIDE) + { + newproc(); + startproc(0, CLMAIN); + } + } + ; + +goto: SGOTO end_spec label + { exgoto($3); thiswasbranch = YES; } + | SASGOTO end_spec name + { exasgoto($3); thiswasbranch = YES; } + | SASGOTO end_spec name opt_comma SLPAR labellist SRPAR + { exasgoto($3); thiswasbranch = YES; } + | SCOMPGOTO end_spec SLPAR labellist SRPAR opt_comma expr + { putcmgo(fixtype($7), nstars, labarray); } + ; + +opt_comma: + | SCOMMA + ; + +call: SCALL end_spec name + { nstars = 0; $$ = $3; } + ; + +callarglist: callarg + { $$ = ($1 ? mkchain($1,0) : 0); } + | callarglist SCOMMA callarg + { if($3) { + if($1) $$ = hookup($1, mkchain($3,0)); + else $$ = mkchain($3,0); + } + } + ; + +callarg: expr + | SSTAR label + { labarray[nstars++] = $2; $$ = 0; } + ; + +stop: SPAUSE + { $$ = 0; } + | SSTOP + { $$ = 1; } + ; + +exprlist: expr + { $$ = mkchain($1, 0); } + | exprlist SCOMMA expr + { $$ = hookup($1, mkchain($3,0) ); } + ; + +end_spec: + { if(parstate == OUTSIDE) + { + newproc(); + startproc(0, CLMAIN); + } + if(parstate < INDATA) enddcl(); + } + ; diff --git a/compilers/pcc/pcc-1.0.0/f77/fcom/gram.expr b/compilers/pcc/pcc-1.0.0/f77/fcom/gram.expr new file mode 100644 index 00000000..e8977a72 --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/fcom/gram.expr @@ -0,0 +1,125 @@ +funarglist: + { $$ = 0; } + | funargs + ; + +funargs: expr + { $$ = mkchain($1, 0); } + | funargs SCOMMA expr + { $$ = hookup($1, mkchain($3,0) ); } + ; + + +expr: uexpr + | SLPAR expr SRPAR { $$ = $2; } + | complex_const + ; + +uexpr: lhs + | simple_const + | expr addop expr %prec SPLUS + { $$ = mkexpr($2, $1, $3); } + | expr SSTAR expr + { $$ = mkexpr(OPSTAR, $1, $3); } + | expr SSLASH expr + { $$ = mkexpr(OPSLASH, $1, $3); } + | expr SPOWER expr + { $$ = mkexpr(OPPOWER, $1, $3); } + | addop expr %prec SSTAR + { if($1 == OPMINUS) + $$ = mkexpr(OPNEG, $2, 0); + else $$ = $2; + } + | expr relop expr %prec SEQ + { $$ = mkexpr($2, $1, $3); } + | expr SEQV expr + { $$ = mkexpr(OPEQV, $1,$3); } + | expr SNEQV expr + { $$ = mkexpr(OPNEQV, $1, $3); } + | expr SOR expr + { $$ = mkexpr(OPOR, $1, $3); } + | expr SAND expr + { $$ = mkexpr(OPAND, $1, $3); } + | SNOT expr + { $$ = mkexpr(OPNOT, $2, 0); } + | expr SCONCAT expr + { $$ = mkexpr(OPCONCAT, $1, $3); } + ; + +addop: SPLUS { $$ = OPPLUS; } + | SMINUS { $$ = OPMINUS; } + ; + +relop: SEQ { $$ = OPEQ; } + | SGT { $$ = OPGT; } + | SLT { $$ = OPLT; } + | SGE { $$ = OPGE; } + | SLE { $$ = OPLE; } + | SNE { $$ = OPNE; } + ; + +lhs: name + { $$ = mkprim($1, 0, 0, 0); } + | name SLPAR opt_expr SCOLON opt_expr SRPAR + { $$ = mkprim($1, 0, $3, $5); } + | name SLPAR funarglist SRPAR + { $$ = mkprim($1, mklist($3), 0, 0); } + | name SLPAR funarglist SRPAR SLPAR opt_expr SCOLON opt_expr SRPAR + { $$ = mkprim($1, mklist($3), $6, $8); } + ; + +opt_expr: + { $$ = 0; } + | expr + ; + +simple: name + { if($1->vclass == CLPARAM) + $$ = cpexpr($1->b_param.paramval); + } + | simple_const + ; + +simple_const: STRUE { $$ = mklogcon(1); } + | SFALSE { $$ = mklogcon(0); } + | SHOLLERITH { $$ = mkstrcon(toklen, token); } + | SICON { $$ = mkintcon( convci(toklen, token) ); } + | SRCON { $$ = mkrealcon(TYREAL, convcd(toklen, token)); } + | SDCON { $$ = mkrealcon(TYDREAL, convcd(toklen, token)); } + ; + +complex_const: SLPAR uexpr SCOMMA uexpr SRPAR + { $$ = mkcxcon($2,$4); } + ; + +bit_const: SHEXCON + { $$ = mkbitcon(4, toklen, token); } + | SOCTCON + { $$ = mkbitcon(3, toklen, token); } + | SBITCON + { $$ = mkbitcon(1, toklen, token); } + ; + +fexpr: unpar_fexpr + | SLPAR fexpr SRPAR + { $$ = $2; } + ; + +unpar_fexpr: lhs + | simple_const + | fexpr addop fexpr %prec SPLUS + { $$ = mkexpr($2, $1, $3); } + | fexpr SSTAR fexpr + { $$ = mkexpr(OPSTAR, $1, $3); } + | fexpr SSLASH fexpr + { $$ = mkexpr(OPSLASH, $1, $3); } + | fexpr SPOWER fexpr + { $$ = mkexpr(OPPOWER, $1, $3); } + | addop fexpr %prec SSTAR + { if($1 == OPMINUS) + $$ = mkexpr(OPNEG, $2, 0); + else $$ = $2; + } + | fexpr SCONCAT fexpr + { $$ = mkexpr(OPCONCAT, $1, $3); } + ; diff --git a/compilers/pcc/pcc-1.0.0/f77/fcom/gram.head b/compilers/pcc/pcc-1.0.0/f77/fcom/gram.head new file mode 100644 index 00000000..07d5d30c --- /dev/null +++ b/compilers/pcc/pcc-1.0.0/f77/fcom/gram.head @@ -0,0 +1,174 @@ +%{ + +#include "defines.h" +#include "defs.h" + +static int nstars; +static int ndim; +static int vartype; +static ftnint varleng; +struct uux dims[8]; +static struct labelblock *labarray[100]; +static int lastwasbranch = NO; +static int thiswasbranch = NO; + +%} + +/* Specify precedences and associativies. */ + +%left SCOMMA +%nonassoc SCOLON +%right SEQUALS +%left SEQV SNEQV +%left SOR +%left SAND +%left SNOT +%nonassoc SLT SGT SLE SGE SEQ SNE +%left SCONCAT +%left SPLUS SMINUS +%left SSTAR SSLASH +%right SPOWER + +%union { + struct labelblock *label; + struct extsym *extsym; + + bigptr bigptr; + chainp chainp; + + ftnint fint; + char *str; + char token; + int num; +} + +%type