diff --git a/.clang-format b/.clang-format index d5e0c3a16..7dced3479 100644 --- a/.clang-format +++ b/.clang-format @@ -7,5 +7,6 @@ IndentCaseLabels: 'true' PointerAlignment: Left TabWidth: '4' UseTab: ForIndentation +SortIncludes: false ... diff --git a/.travis.yml b/.travis.yml index c6e2f5913..f06e5aca3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,12 @@ matrix: include: - os: linux - - os: osx addons: apt: packages: - ed - - openbios-ppc + - qemu-user git: depth: 10 diff --git a/Makefile b/Makefile index 635650bc4..59b4e1a57 100644 --- a/Makefile +++ b/Makefile @@ -63,7 +63,7 @@ PLATDEP = $(INSDIR)/lib/ack .NOTPARALLEL: -MAKECMDGOALS ?= +ack +MAKECMDGOALS ?= +ack +tests BUILD_FILES = $(shell find * -name '*.lua') ifneq ($(shell which ninja),) @@ -88,6 +88,7 @@ $(BUILDDIR)/build.$(BUILDSYSTEM): first/ackbuilder.lua Makefile $(BUILD_FILES) $ @$(LUA) first/ackbuilder.lua \ first/build.lua build.lua \ --$(BUILDSYSTEM) \ + DEFAULT_PLATFORM=$(DEFAULT_PLATFORM) \ OBJDIR=$(OBJDIR) \ BINDIR=$(BINDIR) \ LIBDIR=$(LIBDIR) \ @@ -95,6 +96,7 @@ $(BUILDDIR)/build.$(BUILDSYSTEM): first/ackbuilder.lua Makefile $(BUILD_FILES) $ INSDIR=$(INSDIR) \ PLATIND=$(PLATIND) \ PLATDEP=$(PLATDEP) \ + PREFIX=$(PREFIX) \ AR=$(AR) \ CC=$(CC) \ > $(BUILDDIR)/build.$(BUILDSYSTEM) diff --git a/README b/README index 701581f17..d3273fc0b 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ =================================== © 1987-2005 Vrije Universiteit, Amsterdam - 2016-08-02 + 2017-01-07 INTRODUCTION @@ -19,22 +19,25 @@ probably broken. However, what's there should be sufficient to get things done and to evaluate how the full 6.1 release should work. + SUPPORT ======= Languages: -ANSI C, Pascal, Modula 2, Basic. K&R is supported via the ANSI C compiler. +ANSI C, B, Pascal, Modula 2, Basic. K&R is supported via the ANSI C compiler. Platforms: pc86 produces bootable floppy disk images for 8086 PCs linux386 produces ELF executables for PC Linux systems linux68k produces ELF executables for m68020 Linux systems +linuxppc produces ELF executables for PowerPC Linux systems cpm produces i80 CP/M .COM files rpi produces Raspberry Pi GPU binaries + INSTALLATION ============ @@ -55,6 +58,11 @@ Requirements: - (optionally) ninja; if you've got this, this will be autodetected and give you faster builds. +- (optionally) the qemu suite: if you have this installed, the build system + will detect it automatically and run the test suites for the supported + architectures. Get both the qemu-system-* platform emulators and the qemu-* + userland emulators (only works on Linux). + - about 40MB free in /tmp (or some other temporary directory). - about 6MB in the target directory. @@ -89,6 +97,7 @@ Instructions: The ACK should now be ready to use. + USAGE ===== @@ -111,7 +120,8 @@ Some useful options include: ack figures out which language to use from the file extension: .c C (ANSI or K&R) - .b Basic + .b the PDP-11 dialect of B + .bas Basic .mod Modula-2 .ocm Occam 1 .p Pascal @@ -150,11 +160,17 @@ There are some things you should be aware of. - The ACK uses its own .o format. You won't be able to mix the ACK's object files and another compiler's. +- When compiling together multiple B source files, you need to do some extra + work to initialise them properly otherwise your program will crash on + startup; see the ack(1) and abmodules(1) man pages. + - The distribution contains *everything*, including the weird, ancient, archaic stuff that doesn't work any more and never will, such as the int EM interpreter and the assembler-linkers. Only some of it builds. Look for build.lua files. + + DISCLAIMER ========== @@ -177,6 +193,6 @@ You can find the mailing list on the project's web site: Please enjoy. -David Given (dtrg on Sourceforge) +David Given (davidgiven on Github) dg@cowlark.com -2016-08-02 +2016-11-26 diff --git a/build.lua b/build.lua index cc550cb9e..f7b0ca1ea 100644 --- a/build.lua +++ b/build.lua @@ -9,12 +9,17 @@ vars.plats = { "linux386", "linux68k", "linuxppc", + "osx386", + "osxppc", "qemuppc", "pc86", "rpi", } vars.plats_with_tests = { + "linux386", + "linuxppc", "qemuppc", + "pc86", } local plat_packages = {} @@ -33,6 +38,7 @@ installable { "lang/cem/cemcom.ansi+pkg", "lang/m2/comp+pkg", "lang/pc/comp+pkg", + "lang/b/compiler+pkg", "util/ack+pkg", "util/amisc+pkg", "util/arch+pkg", @@ -43,8 +49,18 @@ installable { "examples+pkg", plat_packages }, - deps = { - test_packages - } } +normalrule { + name = "tests", + ins = { + "first/testsummary.sh", + test_packages + }, + outleaves = { + "stamp" + }, + commands = { + "%{ins}" + } +} diff --git a/examples/build.lua b/examples/build.lua index 631752976..fced8e299 100644 --- a/examples/build.lua +++ b/examples/build.lua @@ -6,6 +6,7 @@ local conly = { local sourcefiles = filenamesof( "./hilo.b", + "./hilo.bas", "./hilo.c", "./hilo.mod", "./hilo.p", diff --git a/examples/hilo.b b/examples/hilo.b index bdde01eab..818d1fb12 100644 --- a/examples/hilo.b +++ b/examples/hilo.b @@ -1,39 +1,108 @@ -1 ' $Source$ -2 ' $State$ -3 ' $Revision$ +# -10 print "Hi there! I'm written in Basic. Before we start, what is your name?" -20 input "> ", PlayerName$ -30 print -40 print "Hello, "; PlayerName$; "!" +buffer[6]; +PlayerName[6]; -100 gosub 1000 -110 print -120 print "Would you like another go?" -130 input "> ", s$ -140 s$ = left$(s$, 1) -150 if s$ = "n" or s$ = "N" then goto 200 -160 print -170 print "Excellent! "; -180 goto 100 -200 print -210 print "Thanks for playing --- goodbye!" -220 end +/* Taken intact from the B reference manual. */ +strcopy(sl ,s2) +{ + auto i; -1000 print "See if you can guess my number." -1010 Number% = rnd(1) mod 100 -1020 Attempts% = 1 + i = 0; + while (lchar(sl, i, char(s2, i)) != '*e') + i++; +} -1030 print -1040 input "> ", guess% -1050 if guess% < Number% then print: print "Try a bit higher." -1060 if guess% > Number% then print: print "Try a bit lower." -1070 if guess% = Number% then goto 1100 -1080 Attempts% = Attempts% + 1 -1090 goto 1030 -1100 print -1110 print "You got it right in only"; Attempts%; -1120 if Attempts% = 1 then print "go"; else print "goes"; -1130 print "!" -1140 return +reads() +{ + extrn buffer; + + putstr("> "); + flush(); + getstr(buffer); +} + +atoi(s) +{ + auto value, sign, i, c; + + i = 0; + if (char(s, i) == '-') + { + sign = -1; + i++; + } + else + sign = 1; + + value = 0; + while ((c = char(s, i++)) != '*e') + value = value*10 + (c - '0'); + + return(value * sign); +} + +rand() +{ + /* Genuinely random; retrieved from random.org */ + return(57); +} + +game() +{ + extrn buffer; + auto Number, Attempts; + auto guess; + + printf("See if you can guess my number.*n"); + + Number = rand() % 100; + Attempts = 1; + + while (1) + { + reads(); + guess = atoi(buffer); + + if (guess == Number) + { + printf("*nYou got it right in only %d %s!*n", Attempts, + (Attempts == 1) ? "go" : "goes"); + return; + } + + if (guess < Number) + printf("*nTry a bit higher.*n"); + if (guess > Number) + printf("*nTry a bit lower.*n"); + Attempts++; + } +} + +main() +{ + extrn buffer, PlayerName; + + printf("*nHi there! I'm written in B. Before we start, what is your name?*n"); + reads(); + strcopy(PlayerName, buffer); + printf("*nHello, %s! ", PlayerName); + + while (1) + { + game(); + printf("*nWould you like another go?*n"); + reads(); + + if ((char(buffer, 0) == 'n') | (char(buffer, 0) == 'N')) + { + printf("*nThanks for playing --- goodbye!*n"); + break; + } + + printf("*nExcellent! "); + } + + return(0); +} diff --git a/examples/hilo.bas b/examples/hilo.bas new file mode 100644 index 000000000..bdde01eab --- /dev/null +++ b/examples/hilo.bas @@ -0,0 +1,39 @@ +1 ' $Source$ +2 ' $State$ +3 ' $Revision$ + +10 print "Hi there! I'm written in Basic. Before we start, what is your name?" +20 input "> ", PlayerName$ +30 print +40 print "Hello, "; PlayerName$; "!" + +100 gosub 1000 +110 print +120 print "Would you like another go?" +130 input "> ", s$ +140 s$ = left$(s$, 1) +150 if s$ = "n" or s$ = "N" then goto 200 +160 print +170 print "Excellent! "; +180 goto 100 +200 print +210 print "Thanks for playing --- goodbye!" +220 end + +1000 print "See if you can guess my number." +1010 Number% = rnd(1) mod 100 +1020 Attempts% = 1 + +1030 print +1040 input "> ", guess% +1050 if guess% < Number% then print: print "Try a bit higher." +1060 if guess% > Number% then print: print "Try a bit lower." +1070 if guess% = Number% then goto 1100 +1080 Attempts% = Attempts% + 1 +1090 goto 1030 +1100 print +1110 print "You got it right in only"; Attempts%; +1120 if Attempts% = 1 then print "go"; else print "goes"; +1130 print "!" +1140 return + diff --git a/examples/paranoia.c b/examples/paranoia.c index f7020f71e..8a25800d9 100644 --- a/examples/paranoia.c +++ b/examples/paranoia.c @@ -15,6 +15,7 @@ This is a public domain adventure and may not be sold for profit */ +#include #include #define MOXIE 13 @@ -32,7 +33,9 @@ int plato_clone=3; int blast_door=0; int killer_count=0; -char get_char() +void character(void); + +char get_char(void) { char c; fflush(stdout); @@ -41,7 +44,7 @@ char get_char() return c; } -more() +void more(void) { printf("---------- More ----------"); #ifdef DEBUG @@ -55,8 +58,7 @@ more() }; } -new_clone(resume) -int resume; +int new_clone(int resume) { printf("\nClone %d just died.\n",clone); if (++clone>6) @@ -75,15 +77,14 @@ int resume; } } -dice_roll(number,faces) -int number, faces; +int dice_roll(int number, int faces) { int i,total=0; for(i=number;i>0;i--) total+= rand()%faces+1; return total; } -instructions() +void instructions(void) { printf("\n\n\n\nWelcome to Paranoia!\n\n"); printf("HOW TO PLAY:\n\n"); @@ -104,7 +105,7 @@ instructions() printf(" If not, you can try again later.\n"); } -character() +void character(void) { printf("===============================================================================\n"); printf("The Character : Philo-R-DMD %d\n", clone); @@ -130,9 +131,7 @@ character() printf("===============================================================================\n"); } -choose(a,aptr,b,bptr) -int a,b; -char *aptr, *bptr; +int choose(int a, char* aptr, int b, char* bptr) { printf("\nSelect \'a\' or \'b\' :\n"); printf(" a - %s.\n b - %s.\n", aptr, bptr); @@ -140,7 +139,7 @@ char *aptr, *bptr; else return b; } -page1() +int page1(void) { printf(" You wake up face down on the red and pink checked E-Z-Kleen linoleum floor.\n"); printf(" You recognise the pattern, it\'s the type preferred in the internal security\nbriefing cells. When you finally look around you, you see that you are alone\n"); @@ -148,7 +147,7 @@ page1() return 57; } -page2() +int page2(void) { printf("\"Greetings,\" says the kindly Internal Security self incrimination expert who\n"); printf("meets you at the door, \"How are we doing today?\" He offers you a doughnut\n"); @@ -166,7 +165,7 @@ page2() else return new_clone(32); } -page3() +int page3(void) { printf("You walk to the nearest Computer terminal and request more information about\n"); printf("Christmas. The Computer says, \"That is an A-1 ULTRAVIOLET ONLY IMMEDIATE\n"); @@ -174,7 +173,7 @@ page3() return choose(4,"You give your correct clearance",5,"You lie and claim Ultraviolet clearance"); } -page4() +int page4(void) { printf("\"That is classified information, Troubleshooter, thank you for your inquiry.\n"); printf(" Please report to an Internal Security self incrimination station as soon as\n"); @@ -182,7 +181,7 @@ page4() return 9; } -page5() +int page5(void) { printf("The computer says, \"Troubleshooter, you are not wearing the correct colour\n"); printf("uniform. You must put on an Ultraviolet uniform immediately. I have seen to\n"); @@ -193,7 +192,7 @@ page5() return choose(6, "You open the package and put on the uniform", 7, "You finally come to your senses and run for it"); } -page6() +int page6(void) { printf("The uniform definitely makes you look snappy and pert. It really looks\n"); printf("impressive, and even has the new lopsided lapel fashion that you admire so\n"); @@ -205,7 +204,7 @@ page6() return 8; } -page7() +int page7(void) { printf("The corridor lights dim and are replaced by red battle lamps as the Security\n"); printf("Breach alarms howl all around you. You run headlong down the corridor and\n"); @@ -232,7 +231,7 @@ page7() return 8; } -page8() +int page8(void) { printf("\"Now, about your question, citizen. Christmas was an old world marketing ploy\n"); printf("to induce lower clearance citizens to purchase vast quantities of goods, thus\n"); @@ -249,7 +248,7 @@ page8() return 10; } -page9() +int page9(void) { int choice; printf("As you walk toward the tubecar that will take you to GDH7-beta, you pass one\n"); @@ -262,7 +261,7 @@ page9() return choice; } -page10() +int page10(void) { int choice; printf("You stroll briskly down the corridor, up a ladder, across an unrailed catwalk,\n"); @@ -290,7 +289,7 @@ page10() } } -page11() +int page11(void) { printf("The printing on the folder says \"Experimental Self Briefing.\"\n"); printf("You open it and begin to read the following:\n"); @@ -321,7 +320,7 @@ page11() return choose(3,"You wish to ask The Computer for more information about Christmas",10,"You have decided to go directly to Goods Distribution Hall 7-beta"); } -page12() +int page12(void) { printf("You walk up to the door and push the button labelled \"push to exit.\"\n"); printf("Within seconds a surly looking guard shoves his face into the small plexiglass\n"); @@ -333,7 +332,7 @@ page12() return choose(11,"You sit down at the table and read the Orange packet",57,"You stare around the room some more"); } -page13() +int page13(void) { printf("You step into the shiny plasteel tubecar, wondering why the shape has always\n"); printf("reminded you of bullets. The car shoots forward the instant your feet touch\n"); @@ -346,7 +345,7 @@ page13() return 14; } -page14() +int page14(void) { printf("You manage to pull yourself out of the tubecar and look around. Before you is\n"); printf("one of the most confusing things you have ever seen, a hallway that is\n"); @@ -360,7 +359,7 @@ page14() return 22; } -page15() +int page15(void) { printf("You are set upon by a runty robot with a queer looking face and two pointy\n"); printf("rubber ears poking from beneath a tattered cap. \"Hey mister,\" it says,\n"); @@ -384,7 +383,7 @@ page15() } } -page16() +int page16(void) { printf("The doll is a good buy for fifty credits; it will make a fine Christmas present\n"); printf("for one of your friends. After the sale the robot rolls away. You can use\n"); @@ -395,7 +394,7 @@ page16() return 22; } -page17() +int page17(void) { int i, robot_hp=15; printf("You whip out your laser and shoot the robot, but not before it squeezes the\n"); @@ -432,7 +431,7 @@ page17() return 22; } -page18() +int page18(void) { printf("You walk to the centre of the hall, ogling like an infrared fresh from the\n"); printf("clone vats. Towering before you is the most unearthly thing you have ever\n"); @@ -448,7 +447,7 @@ page18() else return 20; } -page19() +int page19(void) { printf("Quickly you regain your balance, whirl and fire your laser into the Ultraviolet\n"); printf("citizen behind you. For a moment your heart leaps to your throat, then you\n"); @@ -461,7 +460,7 @@ page19() return choose(34,"You search the body, keeping an eye open for Internal Security",22,"You run away like the cowardly dog you are"); } -page20() +int page20(void) { printf("Oh no! you can\'t keep your balance. You\'re falling, falling head first into\n"); printf("the Christmas beast\'s gaping maw. It\'s a valiant struggle; you think you are\n"); @@ -473,7 +472,7 @@ page20() return 22; } -page21() +int page21(void) { printf("You have been wasting the leading citizens of Alpha Complex at a prodigious\n"); printf("rate. This has not gone unnoticed by the Internal Security squad at GDH7-beta.\n"); @@ -482,7 +481,7 @@ page21() return new_clone(45); } -page22() +int page22(void) { printf("You are searching Goods Distribution Hall 7-beta.\n"); switch(dice_roll(1,4)) @@ -494,7 +493,7 @@ page22() } } -page23() +int page23(void) { printf("You go to the nearest computer terminal and declare yourself a mutant.\n"); printf("\"A mutant, he\'s a mutant,\" yells a previously unnoticed infrared who had\n"); @@ -503,7 +502,7 @@ page23() return choose(28,"You tell them that it was really only a bad joke",24,"You want to fight it out, one against twelve"); } -page24() +int page24(void) { printf("Golly, I never expected someone to pick this. I haven\'t even designed\n"); printf("the 12 citizens who are going to make a sponge out of you. Tell you what,\n"); @@ -511,7 +510,7 @@ page24() return choose(28,"You change your mind and say it was only a bad joke",25,"You REALLY want to shoot it out"); } -page25() +int page25(void) { printf("Boy, you really can\'t take a hint!\n"); printf("They\'re closing in. Their trigger fingers are twitching, they\'re about to\n"); @@ -519,7 +518,7 @@ page25() return choose(28,"You tell them it was all just a bad joke",26,"You are going to shoot"); } -page26() +int page26(void) { printf("You can read the cold, sober hatred in their eyes (They really didn\'t think\n"); printf("it was funny), as they tighten the circle around you. One of them shoves a\n"); @@ -529,19 +528,19 @@ page26() return new_clone(32); } -page27() +int page27(void) { /* doesn't exist. Can't happen with computer version. designed to catch dice cheats */ } -page28() +int page28(void) { printf("They don\'t think it\'s funny.\n"); return 26; } -page29() +int page29(void) { printf("\"Psst, hey citizen, come here. Pssfft,\" you hear. When you peer around\n"); printf("you can see someone\'s dim outline in the shadows. \"I got some information\n"); @@ -559,7 +558,7 @@ page29() } } -page30() +int page30(void) { printf("You step into the shadows and offer the man a thirty credit bill. \"Just drop\n"); printf("it on the floor,\" he says. \"So you\'re looking for the Master Retailer, pssfft?\n"); @@ -586,7 +585,7 @@ page30() } } -page31() +int page31(void) { printf("Like any good troubleshooter you make the least expensive decision and threaten\n"); printf("him for information. With lightning like reflexes you whip out your laser and\n"); @@ -599,7 +598,7 @@ page31() return choose(30,"You pay the 30 credits",22,"You pssfft go away stupid"); } -page32() +int page32(void) { printf("Finally it\'s your big chance to prove that you\'re as good a troubleshooter\n"); printf("as your previous clone. You walk briskly to mission briefing and pick up your\n"); @@ -609,7 +608,7 @@ page32() return 22; } -page33() +int page33(void) { blast_door=1; printf("You release the megabolts on the blast door, then strain against it with your\n"); @@ -622,7 +621,7 @@ page33() else return 36; } -page34() +int page34(void) { printf("You have found a sealed envelope on the body. You open it and read:\n"); printf("\"WARNING: Ultraviolet Clearance ONLY. DO NOT READ.\n"); @@ -650,7 +649,7 @@ page34() return choose(46,"You rush off to the nearest computer terminal to expose the commies",22,"You wander off to look for more evidence"); } -page35() +int page35(void) { printf("\"Oh master,\" you hear through the gun barrel, \"where have you been? It is\n"); printf("time for the great Christmas gifting ceremony. You had better hurry and get\n"); @@ -669,7 +668,7 @@ page35() return new_clone(32); } -page36() +int page36(void) { printf("\"Congratulations, troubleshooter, you have successfully found the lair of the\n"); printf("Master Retailer and completed the Troubleshooter Training Course test mission,\"\n"); @@ -692,7 +691,7 @@ page36() } } -page37() +int page37(void) { printf("\"Come with me please, Troubleshooter,\" says the Green clearance technician\n"); printf("after he has dislodged your head from the cannon. \"You have been participating\n"); @@ -708,7 +707,7 @@ page37() return 38; } -page38() +int page38(void) { printf("\"I am Plato-B-PHI%d, head of mutant propaganda here at the training course.\n",plato_clone); printf("If you have any questions about mutants please come to me. Today I will be\n"); @@ -725,7 +724,7 @@ page38() return choose(39,"You volunteer for the test",40,"You duck behind a chair and hope the instructor doesn\'t notice you"); } -page39() +int page39(void) { printf("You bravely volunteer to test the mutant detection gun. You stand up and walk\n"); printf("down the steps to the podium, passing a very relieved Troubleshooter along the\n"); @@ -743,7 +742,7 @@ page39() return 41; } -page40() +int page40(void) { printf("You breathe a sigh of relief as Plato-B-PHI picks on the other Troubleshooter.\n"); printf("\"You down here in the front,\" says the instructor pointing at the other\n"); @@ -775,7 +774,7 @@ page40() } } -page41() +int page41(void) { printf("You stumble down the hallway of the Troubleshooter Training Course looking for\n"); printf("your next class. Up ahead you see one of the instructors waving to you. When\n"); @@ -789,7 +788,7 @@ page41() return choose(42,"You respond with the proper Illuminati code phrase, \"Ewige Blumenkraft\"",43,"You ignore this secret society contact"); } -page42() +int page42(void) { printf("\"Aha, so you are a member of the elitist Illuminati secret society,\" he says\n"); printf("loudly, \"that is most interesting.\" He turns to the large class already\n"); @@ -799,7 +798,7 @@ page42() return choose(51,"You run for it",52,"You wait for the guard"); } -page43() +int page43(void) { printf("You sit through a long lecture on how to recognise and infiltrate secret\n"); printf("societies, with an emphasis on mimicking secret handshakes. The basic theory,\n"); @@ -815,7 +814,7 @@ page43() return choose(44,"You go looking for a computer terminal",55,"You go to the graduation ceremony immediately"); } -page44() +int page44(void) { printf("You walk down to a semi-secluded part of the training course complex and\n"); printf("activate a computer terminal. \"AT YOUR SERVICE\" reads the computer screen.\n"); @@ -833,7 +832,7 @@ page44() } } -page45() +int page45(void) { printf("\"Hrank Hrank,\" snorts the alarm in your living quarters. Something is up.\n"); printf("You look at the monitor above the bathroom mirror and see the message you have\n"); @@ -847,7 +846,7 @@ page45() return 10; } -page46() +int page46(void) { printf("\"Why do you ask about the communists, Troubleshooter? It is not in the\n"); printf("interest of your continued survival to be asking about such topics,\" says\n"); @@ -855,7 +854,7 @@ page46() return choose(53,"You insist on talking about the communists",54,"You change the subject"); } -page47() +int page47(void) { printf("The Computer orders the entire Vulture squadron to terminate the Troubleshooter\n"); printf("Training Course. Unfortunately you too are terminated for possessing\n"); @@ -867,7 +866,7 @@ page47() return 0; } -page48() +int page48(void) { printf("The tubecar shoots forward as you enter, slamming you back into a pile of\n"); printf("garbage. The front end rotates upward and you, the garbage and the garbage\n"); @@ -877,14 +876,14 @@ page48() return new_clone(45); } -page49() +int page49(void) { printf("The instructor drags your inert body into a specimen detainment cage.\n"); printf("\"He\'ll make a good subject for tomorrow\'s mutant dissection class,\" you hear.\n"); return new_clone(32); } -page50() +int page50(void) { printf("You put down the other Troubleshooter, and then wisely decide to drill a few\n"); printf("holes in the instructor as well; the only good witness is a dead witness.\n"); @@ -893,27 +892,27 @@ page50() return 41; } -page51() +int page51(void) { printf("You run for it, but you don\'t run far. Three hundred strange and exotic\n"); printf("weapons turn you into a freeze dried cloud of soot.\n"); return new_clone(32); } -page52() +int page52(void) { printf("You wisely wait until the instructor returns with a Blue Internal Security\n"); printf("guard. The guard leads you to an Internal Security self incrimination station.\n"); return 2; } -page53() +int page53(void) { printf("You tell The Computer about:\n"); return choose(47,"The commies who have infiltrated the Troubleshooter Training Course\n and the impending People\'s Revolution",54,"Something less dangerous"); } -page54() +int page54(void) { printf("\"Do not try to change the subject, Troubleshooter,\" says The Computer.\n"); printf("\"It is a serious crime to ask about the communists. You will be terminated\n"); @@ -927,7 +926,7 @@ page54() else return new_clone(32); } -page55() +int page55(void) { printf("You and 300 other excited graduates are marched from the lecture hall and into\n"); printf("a large auditorium for the graduation exercise. The auditorium is\n"); @@ -955,7 +954,7 @@ page55() return 0; } -page56() +int page56(void) { printf("That familiar strange feeling of deja\'vu envelops you again. It is hard to\n"); printf("say, but whatever is on the other side of the door does not seem to be intended\n"); @@ -963,15 +962,14 @@ page56() return choose(33,"You open the door and step through",22,"You go looking for more information"); } -page57() +int page57(void) { printf("In the centre of the room is a table and a single chair. There is an Orange\n"); printf("folder on the table top, but you can\'t make out the lettering on it.\n"); return choose(11,"You sit down and read the folder",12,"You leave the room"); } -next_page(this_page) -int this_page; +int next_page(int this_page) { printf("\n"); switch (this_page) @@ -1038,10 +1036,11 @@ int this_page; } } -main() +int main(int argc, const char* argv[]) { /* srand(time(0)); */ instructions(); more(); character(); more(); while((page=next_page(page))!=0) more(); + return 0; } diff --git a/first/testsummary.sh b/first/testsummary.sh new file mode 100755 index 000000000..9ab5daa2f --- /dev/null +++ b/first/testsummary.sh @@ -0,0 +1,50 @@ +#!/bin/sh +echo "" + +succeeding="$(find "$@" -size 0)" +notsucceeding="$(find "$@" ! -size 0)" +if [ "$notsucceeding" != "" ]; then + skipped="$(grep -l @@SKIPPED $notsucceeding)" + timedout="$(grep -l @@TIMEDOUT $notsucceeding)" + failed="$(grep -l @@FAIL $notsucceeding)" +else + skipped= + timedout= + failed= +fi + +for a in $failed $timedout; do + echo "**** $a" + cat $a + echo "" +done + +echo "$(echo "$succeeding" | wc -w) tests passed" +echo "$(echo "$notsucceeding" | wc -w) tests failed to pass" +echo "$(echo "$skipped" | wc -w) were skipped (see build log for details)" +echo "$(echo "$timedout" | wc -w) timed out" +echo "$(echo "$failed" | wc -w) failed" +echo "" + +if [ "$failed" != "" ]; then + echo "Failing test logs:" + for t in $failed; do + echo $t + done + exit 1 +fi +if [ "$failed" != "" -o "$timedout" != "" ]; then + echo "Test status: SAD FACE (tests are failing)" + exit 1 +fi +if [ "$succeeding" = "" ]; then + echo "Test status: PUZZLED FACE (all tests were skipped)" + exit 0 +fi +if [ "$skipped" != "" ]; then + echo "Test status: MILDLY PLEASED FACE (some tests were skipped, but the rest pass)" + exit 0 +fi +echo "Test status: HAPPY FACE (all tests are passing)" +exit 0 + diff --git a/h/out.h b/h/out.h index 45289f313..6aeffc446 100644 --- a/h/out.h +++ b/h/out.h @@ -65,9 +65,9 @@ struct outname { #define RELO1 1 /* 1 byte */ #define RELO2 2 /* 2 bytes */ #define RELO4 3 /* 4 bytes */ -#define RELOPPC 4 /* PowerPC 26-bit address */ -/* relo 5 is unused */ -#define RELOVC4 6 /* VideoCore IV address in 32-bit instruction */ +#define RELOPPC 4 /* PowerPC 26-bit address */ +#define RELOLIS 5 /* PowerPC lis */ +#define RELOVC4 6 /* VideoCore IV address in 32-bit instruction */ #define RELPC 0x2000 /* pc relative */ #define RELBR 0x4000 /* High order byte lowest address. */ diff --git a/lang/b/LICENSE b/lang/b/LICENSE new file mode 100644 index 000000000..db5ca3b4b --- /dev/null +++ b/lang/b/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2013-2016 aap + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/lang/b/README.md b/lang/b/README.md new file mode 100644 index 000000000..d2ab5faf4 --- /dev/null +++ b/lang/b/README.md @@ -0,0 +1,53 @@ +A B Compiler +============ + +abc is a compiler for the [B Programming Language](http://en.wikipedia.org/wiki/B_(programming_language)) that targets x86\_32 processors. It is currently tested under Linux but should work (or at least be easily ported) to other UNIX-like systems. The code is based on [an early C compiler (last1120c)](http://www.cs.bell-labs.com/who/dmr/primevalC.html) by Dennis Ritchie. + +Documentation +------------- + +* [The Programming Language B](http://9p.io/cm/cs/who/dmr/bintro.html) + +* [B Reference by Ken Thompson](http://9p.io/cm/cs/who/dmr/kbman.html) describes a presumably earlier variant of B, which is slightly different from the one described above. The compiler cannot understand it, but I plan to implement a compatibility mode (the differences are minor). + +Implementation +-------------- + +Since B was first implemented for machines with word addressing, some hacking was required to make it work on the byte addressed x86. Addresses filled in by the linker are always byte addresses, so pointers to these addresses are collectively stored at the end of the .data section and are then converted to word addresses at runtime, before main() is called. + +The generated assembly is *very* inefficient, not even constant expressions are reduced at compile time. Also I/O is currently not buffered. + +How to use +---------- + +The installation requires a little configuration: +'abc' is a frontend for the actual compiler which feels somewhat like gcc (it also handles assembling and linking). Before you can use it, set it's BDIR variable to the directory of the B compiler. +In the Makefile, change the directory of the 'install' rule to wherever you want your 'abc' file to reside. +Then type + + make install libs + +which compiles the compiler 'b', installs the 'abc' frontend and compiles the B runtime and library (brt.o and lib.o). + +To compile and link a B program, simply type + + abc -o outfile file1.b [file2.b ...] + +If you want to compile and assemble only: + + abc -c file1.b [file2.b ...] + +or generate only the assembly: + + abc -S file1.b [file2.b ...] + +Examples of B programs are in the 'examples' directory, they are mostly from Brian Kernighan's tutorial. + +Bugs +---- + +Since command line parameters aren't passed word-aligned, B can't handle them easily. brt.s copies the strings to another location and aligns them, the space is not dynamically allocated however and only 256 bytes are available by default. + +The library is incomplete but has some of the most important functions. + +I have only tested the compiler on an x86\_64 gentoo system. diff --git a/lang/b/compiler/b.h b/lang/b/compiler/b.h new file mode 100644 index 000000000..f5a11fd2a --- /dev/null +++ b/lang/b/compiler/b.h @@ -0,0 +1,176 @@ +#include +#include +#include +#include +#include +#include +#include "astring.h" + +#define NCPS 8 /* chars per symbol */ +#define HSHSIZ 400 /* hash table size */ +#define SWSIZ 230 /* switch table size */ +#define CMSIZ 40 /* symbol stack size */ +#define SSIZE 20 /* operator and precedence stack size */ +#define OSSIZ 300*8 /* space for expression tree */ + +#define EOS 04 /* end of string marker */ + +/* + * Holds a B symbol. + * class is one of the storage classes below. + * offset is used depending on class. + */ +struct hshtab { + int class; + int offset; + int dim; + struct hshtab *next; + char name[NCPS+1]; +}; + +struct tnode { + int op; + int value; + struct tnode *tr1; + struct tnode *tr2; +}; + +struct swtab { + int swlab; + int swval; +}; + +extern int wordsize; +extern const char* modulename; +int paramsize; +struct hshtab hshtab[HSHSIZ]; +int hshused; +int eof; +int peekc; +char ctab[128]; +struct hshtab *bsym; +struct hshtab *paraml, *parame; +int cval; +int isn; +char symbuf[NCPS+1]; +FILE *sbufp; +int stack; +struct tnode **cp; +int *space; +int ospace[OSSIZ]; +int retlab; +int nerror; +struct swtab swtab[SWSIZ]; +struct swtab *swp; +int deflab; +extern int contlab; +extern int brklab; + +extern int opdope[]; +extern int line; +extern int peeksym, peeksym2; + +void error(char *s, ...); +void printtoken(int tok, FILE *out); +struct tnode * block(int op, int value, struct tnode *tr1, struct tnode *tr2); +void rcexpr(struct tnode *tr); +void cbranch(struct tnode *t, int lab); +void jump(int lab); +void fnlabel(int l); +void tonativeaddr(void); +void fromnativeaddr(void); +char* manglename(char* name, char prefix); + +#define EOFC 0 +#define SEMI 1 +#define LBRACE 2 +#define RBRACE 3 +#define LBRACK 4 +#define RBRACK 5 +#define LPARN 6 +#define RPARN 7 +#define COLON 8 +#define COMMA 9 +#define HASH 10 + +#define MCALL 15 +#define CALL 16 +#define DECBEF 17 +#define INCBEF 18 +#define DECAFT 19 +#define INCAFT 20 +#define EXCLA 21 +#define NEG 22 +#define AMPER 23 +#define STAR 24 +#define QUEST 25 +#define NOT 26 + +#define PLUS 30 +#define MINUS 31 +#define MOD 32 +#define TIMES 33 +#define DIVIDE 34 +#define OR 35 +#define AND 36 +#define LSHIFT 37 +#define RSHIFT 38 +#define EQUAL 39 +#define NEQUAL 40 +#define LESSEQ 41 +#define LESS 42 +#define GREATEQ 43 +#define GREAT 44 +#define EOR 45 + +#define ASSIGN 49 +#define ASPLUS 50 +#define ASMINUS 51 +#define ASMOD 52 +#define ASTIMES 53 +#define ASDIV 54 +#define ASOR 55 +#define ASAND 56 +#define ASLSH 57 +#define ASRSH 58 +#define ASEQUAL 59 +#define ASNEQL 60 +#define ASLEQ 61 +#define ASLESS 62 +#define ASGTQ 63 +#define ASGREAT 64 +#define ASEOR 65 + +#define CON 70 +#define STRING 71 +#define NAME 72 +#define KEYW 73 + +#define SQUOTE 121 +#define DQUOTE 122 +#define NEWLN 123 +#define SPACE 124 +#define LETTER 125 +#define DIGIT 126 +#define UNKN 127 + +#define SEOF 200 + +/* storage classes */ +#define AUTO 1 +#define EXTERN 2 +#define INTERN 3 +#define ARG 4 +#define KEYWF 5 + +/* keywords */ +#define CASE 3 +#define IF 4 +#define ELSE 5 +#define WHILE 6 +#define SWITCH 7 +#define GOTO 8 +#define RETURN 9 +#define DEFAULT 10 +#define BREAK 11 + diff --git a/lang/b/compiler/b0.c b/lang/b/compiler/b0.c new file mode 100644 index 000000000..7ae35239b --- /dev/null +++ b/lang/b/compiler/b0.c @@ -0,0 +1,1383 @@ +#include "b.h" + +void extdef(void); +struct hshtab * lookup(void); +void blkhed(void); +void blkend(void); +void statement(int d); +struct tnode * tree(void); +void errflush(int o); + +int line = 1; +int peeksym = -1, peeksym2 = -1;; +int contlab = -1; +int brklab = -1; + +int wordsize = 4; +const char* modulename = "bmodule_main"; +int bsymb_part; +int code_part; +int string_part; + +void +init(char *s, int val) +{ + char *sp; + struct hshtab *np; + + sp = symbuf; + while (sp < symbuf+NCPS+1) + if ((*sp++ = *s++) == '\0') + s--; + np = lookup(); + np->class = KEYWF; + np->offset = val; +} + +int +main(int argc, char *argv[]) +{ + + for (;;) { + int opt = getopt(argc, argv, "-w:B:i:o:"); + if (opt == -1) + break; + + switch (opt) { + case 'w': + wordsize = atoi(optarg); + break; + + case 'B': + modulename = aprintf("bmodule_%s", optarg); + break; + + case 'i': + if (freopen(optarg, "r", stdin) == NULL) { + error("Can't find %s", optarg); + exit(1); + } + break; + + case 'o': + if (freopen(optarg, "w", stdout) == NULL) { + error("Can't create %s", optarg); + exit(1); + } + break; + + derfault: + error("Usage: em_b [-w wordsize] [-B modulename] [-i inputfile] [-o outputfile]"); + exit(1); + } + } + + init("auto", AUTO); + init("extrn", EXTERN); + init("case", CASE); + init("if", IF); + init("else", ELSE); + init("while", WHILE); + init("switch", SWITCH); + init("goto", GOTO); + init("return", RETURN); + init("default", DEFAULT); + init("break", BREAK); + + C_init(wordsize, wordsize); + C_open(NULL); + C_magic(); + C_ms_emx(wordsize, wordsize); + bsymb_part = 0; + string_part = 0; + code_part = C_getid(); + C_beginpart(code_part); + while (!eof) { + extdef(); + blkend(); + } + C_endpart(code_part); + C_insertpart(code_part); + + if (string_part) + C_insertpart(string_part); + + C_exa_dnam((char*) modulename); + C_df_dnam((char*) modulename); + if (bsymb_part) + C_insertpart(bsymb_part); + C_rom_cst(0); + + C_close(); + + return nerror != 0; +} + +/* + * Lexer + */ + +int +spnextchar(void) +{ + int c; + + if ((c = peekc) == 0) + c = getchar(); + if (c == '\t') + c = ' '; + else if (c == '\n') { + c = ' '; + line++; + } + peekc = c; + return c; +} + +int +nextchar(void) +{ + while (spnextchar() == ' ') + peekc = 0; + return peekc; +} + +int +subseq(int c, int a, int b) +{ + if (spnextchar() != c) + return a; + peekc = 0; + return b; +} + +/* Only decimal and octal bases, could extend */ +int +getnum(void) +{ + int base; + int c; + + base = 10; + cval = 0; + if ((c=spnextchar()) == '0') + base = 8; + for (; ctab[c] == DIGIT; c = getchar()) + cval = cval*base + c-'0'; + peekc = c; + return CON; +} + +int +mapch(char c) +{ + int a; + + if ((a=getchar()) == c) + return -1; + switch (a) { + + case '\n': + case '\0': + error("Nonterminated string"); + peekc = a; + return -1; + + case '*': + switch (a=getchar()) { + + case 't': + return('\t'); + + case 'n': + return('\n'); + + case '0': + return('\0'); + + case '(': + return('{'); + + case ')': + return('}'); + + case 'e': + return(EOS); + + case '\n': + line++; + return('\n'); + } + } + return a; +} + +int +getcc(void) +{ + char *cp; + int c, cc; + + cval = 0; + cc = 0; + cp = (char*) &cval; + while ((c = mapch('\'')) >= 0) + if (cc++ < wordsize) + *cp++ = c; + if (cc > wordsize) + error("Long character constant"); + return CON; +} + +int +getstr(void) +{ + int c; + int i; + char b; + int partid; + + partid = C_getid(); + C_beginpart(partid); + if (string_part) + C_insertpart(string_part); + + cval = isn++; + C_df_dlb(cval); + for (i = 1; (c = mapch('"')) >= 0; i++) { + b = c; + C_con_scon(&b, 1); + } + + b = 04; + C_con_scon(&b, 1); + + b = 0; + while ((i++%4) != 0) + C_con_scon(&b, 1); + + C_endpart(partid); + string_part = partid; + + return STRING; +} + +struct hshtab * +lookup(void) +{ + int i; + char *sp, *np; + struct hshtab *rp; + + i = 0; + sp = symbuf; + while (sp < symbuf+NCPS) + i += *sp++&0177; + rp = &hshtab[i%HSHSIZ]; + while (*(np = rp->name)) { + for (sp=symbuf; sp < symbuf+NCPS;) + if (*np++ != *sp++) + goto no; + return rp; + no: + if (++rp >= &hshtab[HSHSIZ]) + rp = hshtab; + } + if (++hshused > HSHSIZ) { + error("Symbol table overflow"); + exit(1); + } + rp->class = 0; + rp->offset = 0; + rp->dim = 0; + sp = symbuf; + for (np = rp->name; sp < symbuf+NCPS+1;) + *np++ = *sp++; + return rp; +} + +/* + * Symbol peeking with one peeksym doesn't work if an ASSIGN is only peeked, + * since it itself peeks a symbol, which is then overwritten. + */ + +/* Note: does not push bsyms !! */ +int +pushsym(int sym) +{ + if (peeksym < 0) + peeksym = sym; + else if (peeksym2 < 0) { + peeksym2 = peeksym; + peeksym = sym; + } else + error("Cannot push more than two symbols\n"); + return sym; +} + +int +symbol(void) +{ + int c; + char *sp; + + if (peeksym >= 0) { + c = peeksym; + peeksym = peeksym2; + peeksym2 = -1; + return c; + } + if (peekc) { + c = peekc; + peekc = 0; + } else + if (eof) + return EOFC; + else + c = getchar(); + if (c==EOF) { + eof++; + return(EOFC); + } + +loop: + switch (ctab[c]) { + + case NEWLN: + line++; + /* fall through */ + case SPACE: + c = getchar(); + goto loop; + + case HASH: + /* # is invalid in B; but we handle it out of convenience so that we can read + * in input files that have been run through the C preprocessor. Ideally we + * should only recognise it when it's the first character in a line, but as + * it's not used anywhere else we can get away with recognising it anywhere. + */ + + while ((c = getchar()) == ' ') + ; + + peekc = c; + getnum(); + line = cval; + + while ((c = getchar()) != '\n') + ; + + goto loop; + + case PLUS: + return subseq(c,PLUS,INCBEF); + + case MINUS: + return subseq(c,MINUS,DECBEF); + + case LESS: + if (subseq(c,0,1)) + return LSHIFT; + return subseq('=', LESS, LESSEQ); + + case GREAT: + if (subseq(c,0,1)) + return RSHIFT; + return subseq('=', GREAT, GREATEQ); + + case ASSIGN: + if (subseq(' ',0,1)) + return ASSIGN; + /* avoid peeking a name, which could overwrite + * an already set bsym. */ + if (ctab[peekc = spnextchar()] == LETTER) + return ASSIGN; + c = symbol(); + if (PLUS <= c && c <= EOR) + return c + ASPLUS-PLUS; + if (c == ASSIGN) + return EQUAL; + pushsym(c); + return ASSIGN; + + case EXCLA: + return subseq('=',EXCLA,NEQUAL); + + case DIVIDE: + if (subseq('*',1,0)) + return DIVIDE; + while ((c = spnextchar()) != EOFC) { + peekc = 0; + if (c == '*') { + if (spnextchar() == '/') { + peekc = 0; + c = getchar(); + goto loop; + } + } + } + eof++; + error("Nonterminated comment"); + return EOFC; + + case DIGIT: + peekc = c; + return getnum(); + + case SQUOTE: + return(getcc()); + + case DQUOTE: + return(getstr()); + + case LETTER: + sp = symbuf; + while (ctab[c] == LETTER || ctab[c] == DIGIT) { + if (sp < symbuf+NCPS) + *sp++ = c; + c = getchar(); + } + while (sp < symbuf+NCPS+1) + *sp++ = '\0'; + peekc = c; + bsym = lookup(); + if (bsym->class == KEYWF) { + cval = bsym->offset; + return KEYW; + } + return NAME; + + case UNKN: + error("Unknown character"); + c = getchar(); + goto loop; + } + return (ctab[c]); +} + +/* + * Declarations and Definitions + */ + +/* Declares a list of names to be of storage class "kw". */ +void +declare(int kw) +{ + int o; + + while ((o = symbol()) == NAME) { + if (bsym->class) + error("%s redeclared", bsym->name); + bsym->class = kw; + while ((o = symbol()) == LBRACK) { + if ((o = symbol()) == CON) { + if (bsym->dim) + error("Bad vector"); + bsym->dim = cval + 1; + o = symbol(); + } + if (o != RBRACK) + goto syntax; + } + if (kw == ARG) { + bsym->next = NULL; + if (!paraml) + paraml = bsym; + else + parame->next = bsym; + parame = bsym; + } + if (o != COMMA) + break; + } + if ((o == SEMI && kw != ARG) || (o == RPARN && kw == ARG)) + return; +syntax: + error("Declaration syntax"); + errflush(o); +} + +void +declist(void) +{ + int o; + + while ((o = symbol()) == KEYW && (cval == AUTO || cval == EXTERN)) + declare(cval); + pushsym(o); +} + +void +function(void) +{ + declare(ARG); + statement(1); + C_ret(0); + C_end(paramsize); +} + +void +global(char *s) +{ + C_exa_dnam(manglename(s, 'b')); +} + +void +bsymb(char *s) +{ + int newpart = C_getid(); + C_beginpart(newpart); + if (bsymb_part != 0) + C_insertpart(bsymb_part); + C_rom_dlb(isn, 0); + C_endpart(newpart); + + bsymb_part = newpart; + C_df_dlb(isn++); +} + +void +extdef(void) +{ + int o, dim, i; + char *bs; + char *ms; + int neg; + + if ((o = symbol()) == EOFC || o == SEMI) + return; + if (o != NAME) + goto syntax; + bs = bsym->name; + i = dim = 0; + neg = 0; + switch(o = symbol()) { + + case SEMI: + global(bs); + C_df_dnam(manglename(bs, 'b')); + C_bss_cst(wordsize, 0, 1); + goto done; + + /* init */ + case CON: + case STRING: + case MINUS: + global(bs); + if (o == STRING) + bsymb(bs); + else if (o == MINUS) { + o = symbol(); + if (o != CON) + goto syntax; + cval = -cval; + } + C_df_dnam(manglename(bs, 'b')); + pushsym(o); + goto init; + + /* vector */ + case LBRACK: + if ((o=symbol()) == CON) { + dim = cval + 1; + o=symbol(); + } + if (o != RBRACK) + goto syntax; + global(bs); + if ((o=symbol()) == SEMI) { + bsymb(bs); + C_df_dnam(manglename(bs, 'b')); + C_con_dlb(isn, 0); + C_df_dlb(isn++); + C_bss_cst(wordsize*dim, 0, 1); + goto done; + } + bsymb(bs); + C_df_dnam(manglename(bs, 'b')); + C_con_dlb(isn, 0); + C_df_dlb(isn++); + pushsym(o); + + init: + do { + if ((o=symbol()) != CON && o != STRING && o != NAME) + goto syntax; + if (o == NAME) { + bsymb(NULL); + C_con_dnam(manglename(bsym->name, 'b'), 0); + } else { + if (o == STRING) { + bsymb(NULL); + C_con_dlb(cval, 0); + } else + C_con_cst(cval); + } + i++; + } while ((o=symbol()) == COMMA); + dim = (i > dim) ? i : dim; + if (i == 0) + C_bss_cst((dim-i)*wordsize, 0, 1); + else { + while (dim -i) { + C_con_cst(0); + i++; + } + } + if (o == SEMI) + goto done; + goto syntax; + + /* function */ + case LPARN: + global(bs); + ms = manglename(bs, 'b'); + bsymb(ms); + C_df_dnam(ms); + ms = manglename(bs, 'i'); + C_con_pnam(ms); + C_inp(ms); + C_pro_narg(ms); + function(); + done: + return; + + case EOFC: + return; + } +syntax: + error("External definition syntax"); + printtoken(o, stderr); + errflush(o); + statement(0); +} + +void +blkhed(void) +{ + int al, pl; + struct hshtab *bs; + + declist(); + stack = al = -wordsize; + pl = 0; /* EM parameters start at offset 0. */ + while (paraml) { + paraml = (bs = paraml)->next; + bs->offset = pl; + pl += wordsize; + } + for (bs = hshtab; bs < &hshtab[HSHSIZ]; bs++) + if (bs->name[0]) { + if (bs->class == AUTO) { + bs->offset = al; + if (bs->dim) { + al -= bs->dim*wordsize; + C_lal(al); + al -= wordsize; + fromnativeaddr(); + C_stl(al); + bs->offset = al; + } + al -= wordsize; + } else if (bs->class == ARG) + bs->class = AUTO; + } + paramsize = -al - wordsize; +} + +void +blkend(void) +{ + struct hshtab *np; + + for (np = hshtab; np < &hshtab[HSHSIZ]; np++) + if (np->class != KEYWF) { + np->name[0] = '\0'; + hshused--; + } +} + +/* + * Statements and Expressions + */ + +struct tnode * +pexpr(void) +{ + struct tnode *t; + int o; + + if ((o = symbol()) != LPARN) + goto syntax; + t = tree(); + if ((o = symbol()) != RPARN) + goto syntax; + return t; +syntax: + error("Statement syntax"); + errflush(o); + return NULL; +} + +void +fnlabel(int l) +{ + C_ilb(l); +} + +/* Jump to "lab", if the expression "t" evaluated to 0. */ +void +cbranch(struct tnode *t, int lab) +{ + rcexpr(t); + C_zeq(lab); +} + +void +jump(int lab) +{ + C_bra(lab); +} + +void +pswitch(void) +{ + struct swtab *sswp; + int dl, swlab; + + if (swp == NULL) + swp = swtab; + sswp = swp; + swlab = isn++; + C_lae_dlb(swlab, 0); + C_csb(wordsize); + + dl = deflab; + deflab = 0; + statement(0); + if (!deflab) + deflab = brklab; + + C_df_dlb(swlab); + C_rom_ilb(deflab); + C_rom_cst(swp - sswp); + + while (swp > sswp && swp > swtab) { + --swp; + C_rom_cst(swp->swval); + C_rom_ilb(swp->swlab); + } + + C_df_ilb(brklab); + + deflab = dl; + swp = sswp; +} + +void +statement(int d) +{ + int o, o1, o2; + +stmt: + if ((o = symbol()) == LBRACE) { + if (d) + blkhed(); + while (!eof) { + if ((o = symbol()) == RBRACE) + goto bend; + pushsym(o); + statement(0); + } + error("Missing '}'"); + bend: + return; + } else { + pushsym(o); + if (d) + blkhed(); + } + + switch (o = symbol()) { + + case EOFC: + error("Unexpected EOF"); + + case SEMI: + case RBRACE: + return; + + case KEYW: + switch (cval) { + case GOTO: + if ((o = symbol()) != NAME) + goto syntax; + if (bsym->offset == 0) + bsym->offset = isn++; + jump(bsym->offset); + goto semi; + + case RETURN: + if (pushsym(symbol()) == LPARN) { + rcexpr(pexpr()); + C_ret(wordsize); + } else { + C_ret(0); + } + goto semi; + + case IF: + cbranch(pexpr(), o1=isn++); + statement(0); + if ((o = symbol()) == KEYW && cval == ELSE) { + jump(o2 = isn++); + fnlabel(o1); + statement(0); + fnlabel(o2); + return; + } + pushsym(o); + fnlabel(o1); + return; + + case WHILE: + o1 = contlab; + o2 = brklab; + fnlabel(contlab = isn++); + cbranch(pexpr(), brklab=isn++); + statement(0); + jump(contlab); + fnlabel(brklab); + contlab = o1; + brklab = o2; + return; + + case BREAK: + if (brklab < 0) + error("Nothing to break from"); + jump(brklab); + goto semi; + + /* Not part of B, but very easy to implement */ +/* + case CONTINUE: + if (contlab < 0) + error("Nothing to continue"); + jump(contlab); + goto semi; +*/ + + case SWITCH: + o1 = brklab; + brklab = isn++; + rcexpr(pexpr()); +/* rcexpr(tree()); */ + pswitch(); + brklab = o1; + return; + + case CASE: + if ((o = symbol()) != CON) + goto syntax; + if ((o = symbol()) != COLON) + goto syntax; + if (swp == NULL) { + error("Case not in switch"); + goto stmt; + } + if (swp >= swtab+SWSIZ) + error("Switch table overflow"); + else { + swp->swlab = isn; + (swp++)->swval = cval; + fnlabel(isn++); + } + goto stmt; + + case DEFAULT: + if (swp == NULL) + error("Default not in switch"); + if ((o = symbol()) != COLON) + goto syntax; + deflab = isn++; + fnlabel(deflab); + goto stmt; + } + + error("Unknown keyword"); + goto syntax; + + case NAME: + if (peekc == ':') { + peekc = 0; + if (bsym->class) { + error("Redefinition"); + goto stmt; + } + bsym->class = INTERN; + if (bsym->offset == 0) + bsym->offset = isn++; + fnlabel(bsym->offset); + goto stmt; + } + } + pushsym(o); + rcexpr(tree()); + C_asp(wordsize); + goto semi; + +semi: + if ((o = symbol()) != SEMI) + goto syntax; + return; + +syntax: + error("Statement syntax"); + errflush(o); + goto stmt; +} + +struct tnode * +block(int op, int value, struct tnode *tr1, struct tnode *tr2) +{ + struct tnode t; + int n; + int *p, *ap; + + p = space; + t.op = op; + t.value = value; + t.tr1 = tr1; + t.tr2 = tr2; + ap = (int*) &t; + n = (sizeof(struct tnode)+sizeof(int)-1) & ~sizeof(int); + if (space+n >= &ospace[OSSIZ]) { + error("Expression overflow 1"); + exit(1); + } + while (n--) + *space++ = *ap++; + return (struct tnode *) p; +} + +void +chklval(struct tnode *p) +{ + if (p->op != NAME && p->op != STAR) + error("Lvalue required"); +} + +void +build(int op) +{ + struct tnode *p1, *p2; + int dope; + + /* a[i] -> *(a+i) */ + if (op == LBRACK) { + build(PLUS); + op = STAR; + } + dope = opdope[op]; + if (dope&01) + p2 = *--cp; + p1 = *--cp; + switch (op) { + case QUEST: + if (p2->op != COLON) + error("Illegal conditional"); + break; + + case AMPER: + if (p1->op == STAR) { + *cp++ = p1->tr1; + return; + } + if (p1->op == NAME) { + *cp++ = block(op,0,p1,NULL); + return; + } + error("Illegal lvalue"); + } + if (dope&02) + chklval(p1); + if (dope&01) + *cp++ = block(op,0,p1,p2); + else + *cp++ = block(op,0,p1,NULL); +} + +struct tnode * +tree(void) +{ + struct tnode *cmst[CMSIZ]; + int opst[SSIZE], prst[SSIZE]; + int *op, *pp; + int andflg; + int o, os; + int p, ps; + + space = ospace; + op = opst; + pp = prst; + cp = cmst; + *op = SEOF; + *pp = 06; + andflg = 0; + +advanc: + switch (o=symbol()) { + case NAME: + if (pushsym(symbol()) == LPARN) { /* function */ + if (bsym->class == 0) + bsym->class = EXTERN; + } else if (bsym->class == 0) { + error("%s undefined", bsym->name); + bsym->class = EXTERN; + } + *cp++ = block(NAME,0,(struct tnode *)bsym,NULL); + goto tand; + + case STRING: + *cp++ = block(STRING,cval,NULL,NULL); + goto tand; + + case CON: + caseCON: + *cp++ = block(CON,cval,NULL,NULL); + goto tand; + +tand: + if (cp >= &cmst[CMSIZ]) { + error("Expression overflow 2"); + exit(1); + } + if (andflg) + goto syntax; + andflg = 1; + goto advanc; + + case DECBEF: + case INCBEF: + if (andflg) + o += 2; + goto oponst; + + case EXCLA: + case NOT: + if (andflg) + goto syntax; + goto oponst; + + case MINUS: + if (!andflg) { + if (pushsym(symbol()) == CON) { + symbol(); + cval = -cval; + goto caseCON; + } + o = NEG; + } + andflg = 0; + goto oponst; + + case AND: + case TIMES: + if (andflg) + andflg = 0; + else + if (o == AND) + o = AMPER; + else + o = STAR; + goto oponst; + + case LPARN: + if (andflg) { + o = symbol(); + if (o == RPARN) + o = MCALL; + else { + pushsym(o); + o = CALL; + andflg = 0; + } + } + goto oponst; + + case RPARN: + case RBRACK: + if (!andflg) + goto syntax; + goto oponst; + } + + if (!andflg) + goto syntax; + andflg = 0; + +oponst: + p = (opdope[o]>>9) & 077; +opon1: + ps = *pp; + if (p > ps || (p == ps && (opdope[o]&0200))) { /* right-assoc */ + switch (o) { + case LPARN: + case LBRACK: + case CALL: + p = 04; + } + if (op >= &opst[SSIZE]) { + error("Expression overflow 3"); + exit(1); + } + *++op = o; + *++pp = p; + goto advanc; + } + --pp; + switch (os = *op--) { + case SEOF: + pushsym(o); + return(*--cp); + + case CALL: + if (o != RPARN) + goto syntax; + build(os); + goto advanc; + + case MCALL: + *cp++ = NULL; + os = CALL; + goto fbuild; + + case LPARN: + if (o != RPARN) + goto syntax; + goto advanc; + + case LBRACK: + if (o != RBRACK) + goto syntax; + build(LBRACK); + goto advanc; + + } +fbuild: + build(os); + goto opon1; +syntax: + error("Expression syntax"); + errflush(o); + return NULL; +} + +void +error(char *s, ...) +{ + va_list args; + + va_start(args, s); + nerror++; + fprintf(stderr, "%d: ", line); + vfprintf(stderr, s, args); + putc('\n', stderr); + va_end(args); +} + +void +errflush(int o) +{ + while (o > RBRACE) /* ; { } */ + o = symbol(); + pushsym(o); +} + +/* + * 000001 binary + * 000002 need lvalue + * 000004 relational + * 000010 assignment + * 000100 commutative + * 000200 right-assoc + * 0XX000 precedence + */ +int opdope[] = { + 000000, /* EOFC */ + 000000, /* ; */ + 000000, /* { */ + 000000, /* } */ + 036000, /* [ */ + 002000, /* ] */ + 036000, /* ( */ + 002000, /* ) */ + 014201, /* : */ + 007001, /* , */ + 000000, /* 10 */ + 000000, /* 11 */ + 000000, /* 12 */ + 000000, /* 13 */ + 000000, /* 14 */ + 036001, /* mcall */ + 036001, /* call */ + 034202, /* ++a */ + 034202, /* a++ */ + 034202, /* --a */ + 034202, /* a-- */ + 034200, /* !un */ + 034200, /* -un */ + 034200, /* &un */ + 034200, /* *un */ + 014201, /* ? */ + 034200, /* ~un */ + 000000, /* 27 */ + 000000, /* 28 */ + 000000, /* 29 */ + 030101, /* + */ + 030001, /* - */ + 032001, /* % */ + 032101, /* * */ + 032001, /* / */ + 016101, /* | */ + 020101, /* & */ + 026001, /* << */ + 026001, /* >> */ + 022105, /* == */ + 022105, /* != */ + 024005, /* <= */ + 024005, /* < */ + 024005, /* >= */ + 024005, /* > */ + 017005, /* ^ */ + 000000, /* 46 */ + 000000, /* 47 */ + 000000, /* 48 */ + 012013, /* = */ + 012213, /* =+ */ + 012213, /* =- */ + 012213, /* =% */ + 012213, /* =* */ + 012213, /* =/ */ + 012213, /* =| */ + 012213, /* =& */ + 012213, /* =<< */ + 012213, /* =>> */ + 012213, /* === */ + 012213, /* =!= */ + 012213, /* =<= */ + 012213, /* =< */ + 012213, /* =>= */ + 012213, /* => */ + 012213, /* =^ */ + 000000, /* 66 */ + 000000, /* 67 */ + 000000, /* 68 */ + 000000, /* 69 */ + 000000, /* CON */ + 000000, /* STRING */ + 000000 /* NAME */ +}; + +char ctab[128] = { + EOFC, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, + LETTER, SPACE, NEWLN, SPACE, SPACE, UNKN, UNKN, UNKN, + UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, + UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, + SPACE, EXCLA, DQUOTE, HASH, UNKN, MOD, AND, SQUOTE, + LPARN, RPARN, TIMES, PLUS, COMMA, MINUS, UNKN, DIVIDE, + DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, + DIGIT, DIGIT, COLON, SEMI, LESS, ASSIGN, GREAT, QUEST, + UNKN, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, + LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, + LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, + LETTER, LETTER, LETTER, LBRACK, UNKN, RBRACK, EOR, LETTER, + UNKN, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, + LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, + LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, + LETTER, LETTER, LETTER, LBRACE, OR, RBRACE, NOT, UNKN +}; + +/* debug function */ +void printtoken(int tok, FILE *out) +{ + static char *strtab[128]; + strtab[0] = "EOFC"; + strtab[1] = "SEMI"; + strtab[2] = "LBRACE"; + strtab[3] = "RBRACE"; + strtab[4] = "LBRACK"; + strtab[5] = "RBRACK"; + strtab[6] = "LPARN"; + strtab[7] = "RPARN"; + strtab[8] = "COLON"; + strtab[9] = "COMMA"; + strtab[10] = "HASH"; + + strtab[15] = "MCALL"; + strtab[16] = "CALL"; + strtab[17] = "DECBEF"; + strtab[18] = "INCBEF"; + strtab[19] = "DECAFT"; + strtab[20] = "INCAFT"; + strtab[21] = "EXCLA"; + strtab[22] = "NEG"; + strtab[23] = "AMPER"; + strtab[24] = "STAR"; + strtab[25] = "QUEST"; + strtab[26] = "NOT"; + + strtab[30] = "PLUS"; + strtab[31] = "MINUS"; + strtab[32] = "MOD"; + strtab[33] = "TIMES"; + strtab[34] = "DIVIDE"; + strtab[35] = "OR"; + strtab[36] = "AND"; + strtab[37] = "LSHIFT"; + strtab[38] = "RSHIFT"; + strtab[39] = "EQUAL"; + strtab[40] = "NEQUAL"; + strtab[41] = "LESSEQ"; + strtab[42] = "LESS"; + strtab[43] = "GREATEQ"; + strtab[44] = "GREAT"; + strtab[45] = "EOR"; + + strtab[49] = "ASSIGN"; + strtab[50] = "ASPLUS"; + strtab[51] = "ASMINUS"; + strtab[52] = "ASMOD"; + strtab[53] = "ASTIMES"; + strtab[54] = "ASDIV"; + strtab[55] = "ASOR"; + strtab[56] = "ASAND"; + strtab[57] = "ASLSH"; + strtab[58] = "ASRSH"; + strtab[59] = "ASEQUAL"; + strtab[60] = "ASNEQL"; + strtab[61] = "ASLEQ"; + strtab[62] = "ASLESS"; + strtab[63] = "ASGTQ"; + strtab[64] = "ASGREAT"; + strtab[65] = "ASEOR"; + + strtab[70] = "CON"; + strtab[71] = "STRING"; + strtab[72] = "NAME"; + strtab[73] = "KEYW"; + + strtab[127] = "UNKN"; + + if (tok == CON || tok == STRING) { + fprintf(out, "%s(%d) ", strtab[tok], cval); + return; + } + if (tok == NAME) { + fprintf(out, "%s(%s) ", strtab[tok], symbuf); + return; + } + + fprintf(out, "%s ", strtab[tok]); +} + diff --git a/lang/b/compiler/b1.c b/lang/b/compiler/b1.c new file mode 100644 index 000000000..ca5ae5593 --- /dev/null +++ b/lang/b/compiler/b1.c @@ -0,0 +1,403 @@ +#include "b.h" + +/* + * Code generation (EM) + */ + +static int +shiftsize(void) +{ + switch (wordsize) { + case 1: return 0; + case 2: return 1; + case 4: return 2; + case 8: return 3; + default: + error("unsupported word size"); + exit(1); + } +} + +void +tonativeaddr(void) +{ + C_loc(shiftsize()); + C_slu(wordsize); +} + +void +fromnativeaddr(void) +{ + C_loc(shiftsize()); + C_sru(wordsize); +} + +char* +manglename(char* name, char prefix) +{ + static char buffer[NCPS+3]; + buffer[0] = prefix; + buffer[1] = '_'; + strcpy(buffer+2, name); + return buffer; +} + +void +binary(struct tnode *tr) +{ + rcexpr(tr->tr1); + rcexpr(tr->tr2); +} + +int +pushargs(struct tnode *tr) +{ + int stk; + + if (tr == NULL) + return 0; + if (tr->op == COMMA) { + rcexpr(tr->tr2); + stk = pushargs(tr->tr1); + return stk+wordsize; + } + rcexpr(tr); + return wordsize; +} + +void +lvalexp(struct tnode *tr) +{ + struct hshtab *bs; + char memloc[64]; + + switch (tr->op) { + + case DECBEF: + case INCBEF: + case DECAFT: + case INCAFT: + if (tr->tr1->op == STAR) { + rcexpr(tr->tr1->tr1); + tonativeaddr(); + + if ((tr->op == DECBEF) || (tr->op == INCBEF)) { + C_dup(wordsize); /* ( addr addr -- ) */ + C_loi(wordsize); /* ( addr val -- ) */ + if (tr->op == DECBEF) + C_dec(); /* ( addr newval -- ) */ + else + C_inc(); /* ( addr newval -- ) */ + C_exg(wordsize); /* ( newval addr -- ) */ + C_dup(wordsize*2); /* ( newval addr newval addr -- ) */ + C_sti(wordsize); /* ( newval addr -- ) */ + C_asp(wordsize); /* ( newval -- ) */ + } else { + C_dup(wordsize); /* ( addr addr -- ) */ + C_loi(wordsize); /* ( addr val -- ) */ + C_dup(wordsize*2); /* ( addr val addr val -- ) */ + if (tr->op == DECAFT) + C_dec(); /* ( addr val addr newval -- ) */ + else + C_inc(); /* ( addr val addr newval -- ) */ + C_exg(wordsize); /* ( addr val newval addr -- ) */ + C_sti(wordsize); /* ( addr val -- ) */ + C_exg(wordsize); /* ( val addr -- ) */ + C_asp(wordsize); /* ( val -- ) */ + } + } else { /* NAME, checked in "build" */ + bs = (struct hshtab *) tr->tr1->tr1; + if (bs->class == EXTERN) { + switch (tr->op) { + case INCBEF: + C_ine_dnam(manglename(bs->name, 'b'), 0); + C_loe_dnam(manglename(bs->name, 'b'), 0); + break; + + case DECBEF: + C_dee_dnam(manglename(bs->name, 'b'), 0); + C_loe_dnam(manglename(bs->name, 'b'), 0); + break; + + case INCAFT: + C_loe_dnam(manglename(bs->name, 'b'), 0); + C_ine_dnam(manglename(bs->name, 'b'), 0); + break; + + case DECAFT: + C_loe_dnam(manglename(bs->name, 'b'), 0); + C_dee_dnam(manglename(bs->name, 'b'), 0); + break; + } + } else if (bs->class == AUTO) { + switch (tr->op) { + case INCBEF: + C_inl(bs->offset); + C_lol(bs->offset); + break; + + case DECBEF: + C_del(bs->offset); + C_lol(bs->offset); + break; + + case INCAFT: + C_lol(bs->offset); + C_inl(bs->offset); + break; + + case DECAFT: + C_lol(bs->offset); + C_del(bs->offset); + break; + } + } else + goto classerror; + } + return; + + case ASSIGN: + rcexpr(tr->tr2); + C_dup(wordsize); + if (tr->tr1->op == STAR) { + rcexpr(tr->tr1->tr1); + tonativeaddr(); + C_sti(wordsize); + } else { /* NAME */ + bs = (struct hshtab *) tr->tr1->tr1; + if (bs->class == EXTERN) { + C_ste_dnam(manglename(bs->name, 'b'), 0); + } else if (bs->class == AUTO) { + C_stl(bs->offset); + } else + goto classerror; + } + return; + + case ASPLUS: + case ASMINUS: + case ASMOD: + case ASTIMES: + case ASDIV: + case ASOR: + case ASAND: + case ASLSH: + case ASRSH: + case ASEQUAL: + case ASNEQL: + case ASLEQ: + case ASLESS: + case ASGTQ: + case ASGREAT: + case ASEOR: + tr->op -= ASPLUS-PLUS; + rcexpr(block(ASSIGN,0,tr->tr1,tr)); + return; + } + +classerror: + error("Storage class"); +} + +void +rcexpr(struct tnode *tr) +{ + int o1, o2; + int stk; + struct hshtab *bs; + + if (tr == NULL) + return; + + if (opdope[tr->op]&02) { + lvalexp(tr); + return; + } + + switch (tr->op) { + + case CON: + C_loc(tr->value); + return; + + case STRING: + C_lae_dlb(tr->value, 0); + fromnativeaddr(); + return; + + case NAME: /* only rvalue */ + bs = (struct hshtab *) tr->tr1; + if (bs->class == EXTERN) + C_loe_dnam(manglename(bs->name, 'b'), 0); + else if (bs->class == AUTO) + C_lol(bs->offset); + else + goto classerror; + return; + + case CALL: + stk = pushargs(tr->tr2); + rcexpr(tr->tr1); + tonativeaddr(); + C_cai(); + if (stk) + C_asp(stk); + C_lfr(wordsize); + return; + + case AMPER: + bs = (struct hshtab *) tr->tr1->tr1; + if (bs->class == EXTERN) { + C_lae_dnam(manglename(bs->name, 'b'), 0); + } else if (bs->class == AUTO) { + C_lal(bs->offset); + } else + goto classerror; + fromnativeaddr(); + return; + + case STAR: /* only rvalue */ + rcexpr(tr->tr1); + tonativeaddr(); + C_loi(wordsize); + return; + + case PLUS: + binary(tr); + C_adi(wordsize); + return; + + case MINUS: + binary(tr); + C_sbi(wordsize); + return; + + case TIMES: + binary(tr); + C_mli(wordsize); + return; + + case DIVIDE: + binary(tr); + C_dvi(wordsize); + return; + + case MOD: + binary(tr); + C_rmi(wordsize); + return; + + case AND: + binary(tr); + C_and(wordsize); + return; + + case OR: + binary(tr); + C_ior(wordsize); + return; + + case EOR: + binary(tr); + C_xor(wordsize); + return; + + case LSHIFT: + binary(tr); + C_sli(wordsize); + return; + + case RSHIFT: + binary(tr); + C_sri(wordsize); + return; + + case EQUAL: + case NEQUAL: + case LESS: + case LESSEQ: + case GREAT: + case GREATEQ: + binary(tr); + C_cmi(wordsize); + switch (tr->op) { + case EQUAL: + C_teq(); + break; + case NEQUAL: + C_tne(); + break; + case LESS: + C_tlt(); + break; + case LESSEQ: + C_tle(); + break; + case GREAT: + C_tgt(); + break; + case GREATEQ: + C_tge(); + break; + } + return; + + case EXCLA: + rcexpr(tr->tr1); + C_teq(); + return; + + case NEG: + rcexpr(tr->tr1); + C_ngi(wordsize); + return; + + case NOT: + rcexpr(tr->tr1); + C_com(wordsize); + return; + + case QUEST: + cbranch(tr->tr1, o1=isn++); + rcexpr(tr->tr2->tr1); + jump(o2 = isn++); + fnlabel(o1); + rcexpr(tr->tr2->tr2); + fnlabel(o2); + return; + + default: + error("Can't print tree (op: %d)", tr->op); + } + +classerror: + error("Storage class"); +} + +/* Prints the tree in RPN, for debugging */ +/* +void +rcexpr(struct tnode *tr) +{ + struct hshtab *bs; + + if (tr == NULL) + printf("(NULL) "); + else if (tr->op == CON) + printf("%d ", tr->value); + else if (tr->op == STRING) + printf("s(L%d) ", tr->value); + else if (tr->op == NAME) { + bs = (struct hshtab *)tr->tr1; + if (bs->class == AUTO) + printf("%s(%d) ", bs->name, bs->offset); + else + printf("%s ", bs->name); + } else { + rcexpr(tr->tr1); + if (opdope[tr->op]&01) + rcexpr(tr->tr2); + printtoken(tr->op, stdout); + } +} +*/ diff --git a/lang/b/compiler/build.lua b/lang/b/compiler/build.lua new file mode 100644 index 000000000..c647f6036 --- /dev/null +++ b/lang/b/compiler/build.lua @@ -0,0 +1,28 @@ + +cprogram { + name = "em_b", + srcs = { + "./*.c", + }, + deps = { + "./*.h", + "modules+headers", + "modules/src/alloc+lib", + "modules/src/data+lib", + "modules/src/em_code+lib_k", + "modules/src/em_data+lib", + "modules/src/em_mes+lib", + "modules/src/print+lib", + "modules/src/string+lib", + "modules/src/system+lib", + } +} + +installable { + name = "pkg", + map = { + ["$(PLATDEP)/em_b"] = "+em_b", + ["$(INSDIR)/share/man/man6/em_b.6"] = "./em_b.6" + } +} + diff --git a/lang/b/compiler/em_b.6 b/lang/b/compiler/em_b.6 new file mode 100644 index 000000000..f7030f214 --- /dev/null +++ b/lang/b/compiler/em_b.6 @@ -0,0 +1,53 @@ +.TH EM_B 6 2017-01-18 +.ad +.SH NAME +em_b \- ACK B compiler +.SH SYNOPSIS +.B ~em/lib/ack/em_b +.RI [ options ] +.SH DESCRIPTION +.I em_b +is a port of the ABC B compiler to the ACK. +Interested parties will be +interested in the upstream distribution here: +.nf +.sp +https://github.com/aap/abc +.fi +.PP +However, the version here has been heavily modified \(em bug reports should be +filed with the ACK, not with the upstream compiler. +.PP +Since B was designed for machines with word addressing, some hacking is +required to make it work on modern, byte addressed machines. +The generated +code expects B variables to contain word addresses, and then generates +code to transform these into native addresses before use (which, +unfortunately, impacts performance). +However, the ACK's linker doesn't know +how to emit word addresses into the program's data sections, and so a +separate fixup stage has to happen at runtime, just before \fBmain()\fP, +to convert the byte addresses into word addresses. +.PP +The end result is that using multiple source files with B is somewhat +unwieldy, requiring each module to be explicitly named and then an extra +stage to generate the fixup code. +See the \fBack\fP(1) and \fBabmodules\fP(1) for details. +.SH OPTIONS +.I em_b +accepts the following flags: +.IP \-w\ \fIsize\fP +Sets the word size, used for scaling addresses. +Usually either 2 or 4. +.IP \-B\ \fIname\fP +Sets the name of the module currently being compiled (used to generate the +fixup table symbol name). +Defaults to \fImain\fP if not specified. +.IP \-i\ \fIfilename\fP +The source B file. +.IP \-o\ \fIfilename\fP +The output compact EM bytecode file. +.SH SEE ALSO +\fIack\fR(1), \fIabmodules\fR(1) +.SH REMARKS +It is very unlikely the \fIem_b\fP will ever be useful for anything. diff --git a/lang/b/distr/Makefile b/lang/b/distr/Makefile new file mode 100644 index 000000000..283848647 --- /dev/null +++ b/lang/b/distr/Makefile @@ -0,0 +1,15 @@ +CFLAGS=-Wall -Wextra +b: b0.o b1.o + cc b0.o b1.o -o b +b0.o: b0.c b.h +b1.o: b1.c b.h + +libs: + ./abc -c brt.s lib.b + +install: b abc + cp abc $(HOME)/bin + +%.o: %.s + as --32 $^ -o $@ + diff --git a/lang/b/distr/abc b/lang/b/distr/abc new file mode 100755 index 000000000..21cdda485 --- /dev/null +++ b/lang/b/distr/abc @@ -0,0 +1,95 @@ +#!/bin/sh +BDIR="$HOME/abc" +objs="$BDIR/brt.o $BDIR/lib.o" +BC="$BDIR/b" + +# compile in.b [out.s] +compile() { + if [ "${1##*.}" != "b" ]; then + echo "Error: can only compile b files" >&2 + exit 1 + fi + cout=$2 + [ "$cout" != "" ] || cout=${1%b}s + tmp1=`mktemp`; tmp2=`mktemp` + $BC $1 $tmp2 $tmp1 + retval=$? + cat $tmp1 $tmp2 > $cout + rm $tmp1 $tmp2 + [ $retval -eq 0 ] || rm $cout && return $retval + echo $cout + return $retval +} + +# assemble in.{sb} [out.o] +assemble() { + atmp="" + ain=$1 + aout=$2; + if [ "${1##*.}" = "b" ]; then + [ "$aout" != "" ] || aout=${ain%b}o + ain=`mktemp --suffix=.s` + compile $1 $ain >/dev/null || return 1 + atmp="foo" + elif [ "${1##*.}" = "s" ]; then + [ "$aout" != "" ] || aout=${ain%s}o + else + echo "Error: can only compile b and s files" >&2 + exit 1 + fi + as --32 -g $ain -o $aout + [ "$atmp" != "" ] && rm $ain + echo $aout +} + +out="" +action="link" +while getopts "o:Sc" o +do case "$o" in + o) out="$OPTARG";; + S) action=compile;; + c) action=assemble;; + esac +done +shift $(($OPTIND - 1)) + +# ignore -o option if more than one file given and not linking objs +if [ $# -gt 1 ]; then + if [ "$action" != "link" ]; then + out="" + fi +fi + +[ $# -ne 1 ] && havelist=yes +tmpobjs="" +for i in $@; do + if [ "$action" != "link" ]; then + [ "$havelist" = "yes" ] && echo $i: + $action $i $out >/dev/null + [ $? -eq 0 ] || break=1 + else + if [ "${i##*.}" = "o" ]; then + objs="$objs $i" + else + [ "$havelist" = "yes" ] && echo $i: + ltmp=`mktemp --suffix=.o` + tmpobjs="$tmpobjs $ltmp" + assemble $i $ltmp >/dev/null + [ $? -eq 0 ] || break=1 + fi + fi +done +if [ $break ]; then + [ "$tmpobjs" = "" ] || rm $tmpobjs + echo "Error" >&2 + exit 1 +fi +if [ "$action" = "link" ]; then + if [ "$out" = "" ]; then + out="-o a.out" + else + out="-o $out" + fi + ld -m elf_i386 -T $BDIR/link.ld $out $objs $tmpobjs + rm $tmpobjs +fi diff --git a/lang/b/distr/brt.s b/lang/b/distr/brt.s new file mode 100644 index 000000000..18f4fb351 --- /dev/null +++ b/lang/b/distr/brt.s @@ -0,0 +1,151 @@ + .globl _argv + .data + .align 4 + .comm argstr,256,4 +_argv: .long 0 + + .text + .globl start +start: + # clear bss (could be done better) + # is it actually necessary? + mov $__bss,%eax +1: + movb $0,(%eax) + inc %eax + cmp $__ebss,%eax + jbe 1b + + # copy command line args (can't use them directly, not aligned) + mov %esp,%eax + shr $2,%eax + mov %eax,_argv + mov (%esp),%ecx # number of arguments + mov $argstr,%edi +1: + mov (%esp,%ecx,4),%esi + mov %edi,%eax + shr $2,%eax + mov %eax,(%esp,%ecx,4) + call cpystr + loop 1b + + call bsymbs + mov _main,%eax + shl $2,%eax + call *%eax + mov %eax,%ebx + mov $1,%eax + int $0x80 + +# copy string from esi to edi and convert '\0' to B's '*e', align edi +cpystr: + mov (%esi),%al + test %al,%al + jz 1f + mov %al,(%edi) + inc %edi + inc %esi + jmp cpystr +1: + movb $04,(%edi) + inc %edi + add $3,%edi + and $~3,%edi + ret + +# shift addresses filled in by the linker 2 bits to the right +# so B only ever sees word addresses +bsymbs: + mov $__bsymb,%eax +1: + cmp $__ebsymb,%eax + jge 1f + mov (%eax),%ebx + mov (%ebx),%ecx + shr $2,%ecx + mov %ecx,(%ebx) + add $4,%eax + jmp 1b +1: + ret + + .globl retrn +retrn: + mov %ebp,%esp + pop %ebp + ret + +# handle switch table: +# eax has the value, ebx the address of the switch table + .globl bswitch +bswitch: + xor %ecx,%ecx +1: + mov (%ebx,%ecx,8),%edx + mov 4(%ebx,%ecx,8),%edi + test %edi,%edi + jz 1f # default (last in table) + cmp %eax,%edx + je 2f + inc %ecx + jmp 1b +1: + jmp *%edx +2: + jmp *%edi + +# +# Library functions in assembly +# + .globl _exit + .data + .align 4 + .section .bsymb; .long _exit; .data +_exit: .long 1f + .text + .align 4 +1: mov $1,%eax + mov $0,%ebx + int $0x80 + + .globl _write + .data + .align 4 + .section .bsymb; .long _write; .data +_write: .long 1f + .text + .align 4 +1: mov 4(%esp),%ebx + mov 8(%esp),%ecx + shl $2,%ecx + mov 12(%esp),%edx + mov $4,%eax + int $0x80 + ret + + .globl _read + .data + .align 4 + .section .bsymb; .long _read; .data +_read: .long 1f + .text + .align 4 +1: mov 4(%esp),%ebx + mov 8(%esp),%ecx + shl $2,%ecx + mov 12(%esp),%edx + mov $3,%eax + int $0x80 + ret + + .globl _inv + .data + .align 4 + .section .bsymb; .long _inv; .data +_inv: .long 1f + .text + .align 4 +1: mov 4(%esp),%eax + not %eax + ret diff --git a/lang/b/distr/examples/1_var.b b/lang/b/distr/examples/1_var.b new file mode 100644 index 000000000..aa315442f --- /dev/null +++ b/lang/b/distr/examples/1_var.b @@ -0,0 +1,7 @@ +main() { + auto a, b, c, sum; + + a = 1; b = 2; c = 3; + sum = a+b+c; + putnumb(sum); +} diff --git a/lang/b/distr/examples/2_ext.b b/lang/b/distr/examples/2_ext.b new file mode 100644 index 000000000..a8deac665 --- /dev/null +++ b/lang/b/distr/examples/2_ext.b @@ -0,0 +1,9 @@ +main() { + extrn a, b, c; + putchar(a); putchar(b); putchar(c); putchar('!*n'); +} + +a 'hell'; +b 'o, w'; +c 'orld'; + diff --git a/lang/b/distr/examples/3_fun.b b/lang/b/distr/examples/3_fun.b new file mode 100644 index 000000000..16d740964 --- /dev/null +++ b/lang/b/distr/examples/3_fun.b @@ -0,0 +1,13 @@ +main() { + extrn a, b, c, d; + put2char(a,b); + put2char(c,d); +} + +put2char(x,y) { +putchar(x); +putchar(y); +} + +a 'hell'; b 'o, w'; c 'orld'; d '!*n'; + diff --git a/lang/b/distr/examples/4_goto.b b/lang/b/distr/examples/4_goto.b new file mode 100644 index 000000000..2d5256afc --- /dev/null +++ b/lang/b/distr/examples/4_goto.b @@ -0,0 +1,7 @@ +main() { + auto c; +read: + c= getchar(); + putchar(c); + if(c != '*n') goto read; +} diff --git a/lang/b/distr/examples/5_while.b b/lang/b/distr/examples/5_while.b new file mode 100644 index 000000000..13baa0cac --- /dev/null +++ b/lang/b/distr/examples/5_while.b @@ -0,0 +1,10 @@ +main() { + auto c; + while (1) { + while ( (c=getchar()) != ' ') + if (putchar(c) == '*n') exit(); + putchar( '*n' ); + while ( (c=getchar()) == ' '); /* skip blanks */ + if (putchar(c)=='*n') exit(); + } +} diff --git a/lang/b/distr/examples/printargs.b b/lang/b/distr/examples/printargs.b new file mode 100644 index 000000000..444932054 --- /dev/null +++ b/lang/b/distr/examples/printargs.b @@ -0,0 +1,10 @@ +main() { + extrn argv; + auto i; + + i = 1; + printf("%d args:*n", argv[0]); + while (i <= argv[0]) + printf("%s*n", argv[i++]); + return(0); +} diff --git a/lang/b/distr/lib.b b/lang/b/distr/lib.b new file mode 100644 index 000000000..9e274eb92 --- /dev/null +++ b/lang/b/distr/lib.b @@ -0,0 +1,111 @@ +char(s, n) + return((s[n/4]>>8*(n%4))&0377); /* s[n/4] */ + +lchar(s, n, char) { + auto i; + i = 8*(n%4); + char = (char&0377)<> 8; + } + write(1, &char, 4-i); + return(char); +} + +getchar() { + auto char; + + char = 0; + read(1, &char, 1); + return(char); +} + +printn(n,b) { + extrn putchar; + auto a; + + if (a = n/b) + printn(a, b); + putchar(char("0123456789ABCDEF", n%b)); +} + +putnumb(n) { + printn(n,10); + putchar('*n'); +} + +putstr(s) { + auto c, i; + + i = 0; + while ((c = char(s,i++)) != '*e') + putchar(c); +} + +getstr(s) { + auto c, i; + + while ((c = getchar()) != '*n') + lchar(s,i++,c); + lchar(s,i,'*e'); + return(s); +} + +printf(fmt, x1,x2,x3,x4,x5,x6,x7,x8,x9) { + extrn printn, char, putchar; + auto adx, x, c, i, j; + + i = 0; + adx = &x1; +loop: + while((c=char(fmt,i++)) != '%') { + if(c == '*e') + return; + putchar(c); + } + x = *adx++; + switch (c = char(fmt,i++)) { + + case 'd': + case 'o': + if(x < 0) { + x = -x; + putchar('-'); + } + printn(x, c=='o'?8:10); + goto loop; + + case 'x': + if(x < 0) { + x = -x; + putchar('-'); + } + printn(x, 16); + goto loop; + + case 'c': + putchar(x); + goto loop; + + case 's': + j = 0; + while((c=char(x,j++)) != '*e') + putchar(c); + goto loop; + } + putchar('%'); + i--; + adx--; + goto loop; +} + diff --git a/lang/b/distr/link.ld b/lang/b/distr/link.ld new file mode 100644 index 000000000..fd0fb71ce --- /dev/null +++ b/lang/b/distr/link.ld @@ -0,0 +1,21 @@ +OUTPUT_FORMAT("elf32-i386") +OUTPUT_ARCH(i386) + +ENTRY(start) + +SECTIONS +{ + . = 0x400000; + .text : { *(.text) } + . = 0x8000000; + .data : { + *(.data) + __bsymb = .; + *(.bsymb) + __ebsymb = .; + } + . = ALIGN(16); + __bss = .; + .bss : { *(.bss) } + __ebss = .; +} diff --git a/lang/b/lib/b.h b/lang/b/lib/b.h new file mode 100644 index 000000000..1125452cd --- /dev/null +++ b/lang/b/lib/b.h @@ -0,0 +1,28 @@ +#ifndef B_H +#define B_H + +#include +#include + +#if EM_PSIZE == 2 +#define SHIFT 1 +#elif EM_PSIZE == 4 +#define SHIFT 2 +#elif EM_PSIZE == 8 +#define SHIFT 3 +#else +#error Unsupported EM_PSIZE +#endif + +extern FILE* input_unit; +extern FILE* output_unit; + +#define END 4 + +extern uintptr_t* bmodule_main[]; + +extern void patch_addresses(uintptr_t** p); + +extern void binit(void); + +#endif diff --git a/lang/b/lib/build.lua b/lang/b/lib/build.lua new file mode 100644 index 000000000..62ae88966 --- /dev/null +++ b/lang/b/lib/build.lua @@ -0,0 +1,27 @@ +include("plat/build.lua") + +for _, plat in ipairs(vars.plats) do + acklibrary { + name = "lib_"..plat, + srcs = { + "./*.c", + "./*.e", + }, + hdrs = {}, -- must be empty + deps = { + "./*.h", + "h+emheaders", + "lang/cem/libcc.ansi/headers+pkg", + "plat/"..plat.."/include+pkg", + }, + vars = { plat = plat } + } + + installable { + name = "pkg_"..plat, + map = { + ["$(PLATIND)/"..plat.."/libb.a"] = "+lib_"..plat, + } + } +end + diff --git a/lang/b/lib/init.c b/lang/b/lib/init.c new file mode 100644 index 000000000..b7ad01f08 --- /dev/null +++ b/lang/b/lib/init.c @@ -0,0 +1,10 @@ +#include "b.h" +#include +#include +#include + +void binit(void) +{ + patch_addresses(bmodule_main); +} + diff --git a/lang/b/lib/main.c b/lang/b/lib/main.c new file mode 100644 index 000000000..b583a4309 --- /dev/null +++ b/lang/b/lib/main.c @@ -0,0 +1,186 @@ +#include "b.h" +#include +#include +#include + +extern intptr_t i_main(intptr_t argc, const char* argv[]); + +FILE* input_unit; +FILE* output_unit; + +static intptr_t i_char(intptr_t s, intptr_t n) +{ + const char* p = (const char*)(s< 0); + + do + fputc(s[--i], output_unit); + while (i > 0); +} + +static void i_printf(intptr_t s, ...) +{ + char* p = (char*)(s<>= SHIFT; + } +} + +int main(int argc, const char* argv[]) +{ + patch_addresses(bmodule_stdlib); + binit(); + input_unit = stdin; + output_unit = stdout; + return i_main(argc, NULL); +} diff --git a/lang/basic/lib/build.lua b/lang/basic/lib/build.lua index 71710a542..cff3b57ca 100644 --- a/lang/basic/lib/build.lua +++ b/lang/basic/lib/build.lua @@ -10,8 +10,8 @@ for _, plat in ipairs(vars.plats) do hdrs = {}, -- must be empty deps = { "h+emheaders", - "lang/cem/libcc.ansi/headers+headers", - "plat/"..plat.."/include+headers", + "lang/cem/libcc.ansi/headers+pkg", + "plat/"..plat.."/include+pkg", }, vars = { plat = plat } } diff --git a/lang/basic/src/basic.lex b/lang/basic/src/basic.lex index 4eb9e1659..3ee185e3f 100644 --- a/lang/basic/src/basic.lex +++ b/lang/basic/src/basic.lex @@ -522,7 +522,7 @@ scanstring() yylval.integer= genemlabel(); C_rom_dlb((label)i,(arith)0); C_rom_icon("9999",(arith)BEMINTSIZE); - C_rom_icon(itoa(length),(arith)BEMINTSIZE); + C_rom_icon(myitoa(length),(arith)BEMINTSIZE); } #ifdef YYDEBUG if (yydebug) print("STRVALUE found\n"); diff --git a/lang/basic/src/bem.h b/lang/basic/src/bem.h index eb1435802..a92cff0b8 100644 --- a/lang/basic/src/bem.h +++ b/lang/basic/src/bem.h @@ -72,5 +72,5 @@ extern int dataused; extern Linerecord *currline; -extern char *itoa(); +extern char *myitoa(); extern char *salloc(); diff --git a/lang/basic/src/gencode.c b/lang/basic/src/gencode.c index 8fb611dc0..710de169d 100644 --- a/lang/basic/src/gencode.c +++ b/lang/basic/src/gencode.c @@ -670,7 +670,7 @@ gendata() C_df_dnam("datfdes"); C_rom_dnam("datfname",(arith)0); C_rom_cst((arith)1); - C_rom_cst((arith)(itoa(strlen(datfname)))); + C_rom_cst((arith)(myitoa(strlen(datfname)))); C_df_dnam("dattdes"); C_rom_dnam("dattyp",(arith)0); C_rom_cst((arith)1); diff --git a/lang/basic/src/util.c b/lang/basic/src/util.c index ff98cf82b..a85339bc5 100644 --- a/lang/basic/src/util.c +++ b/lang/basic/src/util.c @@ -69,7 +69,7 @@ illegalcmd() -char *itoa(i) +char *myitoa(i) int i; { static char buf[30]; diff --git a/lang/basic/test/bull.b b/lang/basic/test/bull.bas similarity index 100% rename from lang/basic/test/bull.b rename to lang/basic/test/bull.bas diff --git a/lang/basic/test/buzzword.b b/lang/basic/test/buzzword.bas similarity index 100% rename from lang/basic/test/buzzword.b rename to lang/basic/test/buzzword.bas diff --git a/lang/basic/test/checker.b b/lang/basic/test/checker.bas similarity index 100% rename from lang/basic/test/checker.b rename to lang/basic/test/checker.bas diff --git a/lang/basic/test/creator.b b/lang/basic/test/creator.bas similarity index 100% rename from lang/basic/test/creator.b rename to lang/basic/test/creator.bas diff --git a/lang/basic/test/grafiek.b b/lang/basic/test/grafiek.bas similarity index 100% rename from lang/basic/test/grafiek.b rename to lang/basic/test/grafiek.bas diff --git a/lang/basic/test/gunner.b b/lang/basic/test/gunner.bas similarity index 100% rename from lang/basic/test/gunner.b rename to lang/basic/test/gunner.bas diff --git a/lang/basic/test/learn.b b/lang/basic/test/learn.bas similarity index 100% rename from lang/basic/test/learn.b rename to lang/basic/test/learn.bas diff --git a/lang/basic/test/opg1.b b/lang/basic/test/opg1.bas similarity index 100% rename from lang/basic/test/opg1.b rename to lang/basic/test/opg1.bas diff --git a/lang/basic/test/opg2.b b/lang/basic/test/opg2.bas similarity index 100% rename from lang/basic/test/opg2.b rename to lang/basic/test/opg2.bas diff --git a/lang/basic/test/opg3.b b/lang/basic/test/opg3.bas similarity index 100% rename from lang/basic/test/opg3.b rename to lang/basic/test/opg3.bas diff --git a/lang/basic/test/opg4.b b/lang/basic/test/opg4.bas similarity index 100% rename from lang/basic/test/opg4.b rename to lang/basic/test/opg4.bas diff --git a/lang/basic/test/opg5.b b/lang/basic/test/opg5.bas similarity index 100% rename from lang/basic/test/opg5.b rename to lang/basic/test/opg5.bas diff --git a/lang/basic/test/opg6.b b/lang/basic/test/opg6.bas similarity index 100% rename from lang/basic/test/opg6.b rename to lang/basic/test/opg6.bas diff --git a/lang/basic/test/som4.b b/lang/basic/test/som4.bas similarity index 100% rename from lang/basic/test/som4.b rename to lang/basic/test/som4.bas diff --git a/lang/basic/test/test01.b b/lang/basic/test/test01.bas similarity index 100% rename from lang/basic/test/test01.b rename to lang/basic/test/test01.bas diff --git a/lang/basic/test/test02.b b/lang/basic/test/test02.bas similarity index 100% rename from lang/basic/test/test02.b rename to lang/basic/test/test02.bas diff --git a/lang/basic/test/test03.b b/lang/basic/test/test03.bas similarity index 100% rename from lang/basic/test/test03.b rename to lang/basic/test/test03.bas diff --git a/lang/basic/test/test04.b b/lang/basic/test/test04.bas similarity index 100% rename from lang/basic/test/test04.b rename to lang/basic/test/test04.bas diff --git a/lang/basic/test/test05.b b/lang/basic/test/test05.bas similarity index 100% rename from lang/basic/test/test05.b rename to lang/basic/test/test05.bas diff --git a/lang/basic/test/test06.b b/lang/basic/test/test06.bas similarity index 100% rename from lang/basic/test/test06.b rename to lang/basic/test/test06.bas diff --git a/lang/basic/test/test07.b b/lang/basic/test/test07.bas similarity index 100% rename from lang/basic/test/test07.b rename to lang/basic/test/test07.bas diff --git a/lang/basic/test/test08.b b/lang/basic/test/test08.bas similarity index 100% rename from lang/basic/test/test08.b rename to lang/basic/test/test08.bas diff --git a/lang/basic/test/test09.b b/lang/basic/test/test09.bas similarity index 100% rename from lang/basic/test/test09.b rename to lang/basic/test/test09.bas diff --git a/lang/basic/test/test10.b b/lang/basic/test/test10.bas similarity index 100% rename from lang/basic/test/test10.b rename to lang/basic/test/test10.bas diff --git a/lang/basic/test/test11.b b/lang/basic/test/test11.bas similarity index 100% rename from lang/basic/test/test11.b rename to lang/basic/test/test11.bas diff --git a/lang/basic/test/test12.b b/lang/basic/test/test12.bas similarity index 100% rename from lang/basic/test/test12.b rename to lang/basic/test/test12.bas diff --git a/lang/basic/test/test13.b b/lang/basic/test/test13.bas similarity index 100% rename from lang/basic/test/test13.b rename to lang/basic/test/test13.bas diff --git a/lang/basic/test/test14.b b/lang/basic/test/test14.bas similarity index 100% rename from lang/basic/test/test14.b rename to lang/basic/test/test14.bas diff --git a/lang/basic/test/test15.b b/lang/basic/test/test15.bas similarity index 100% rename from lang/basic/test/test15.b rename to lang/basic/test/test15.bas diff --git a/lang/basic/test/test16.b b/lang/basic/test/test16.bas similarity index 100% rename from lang/basic/test/test16.b rename to lang/basic/test/test16.bas diff --git a/lang/basic/test/test17.b b/lang/basic/test/test17.bas similarity index 100% rename from lang/basic/test/test17.b rename to lang/basic/test/test17.bas diff --git a/lang/basic/test/test18.b b/lang/basic/test/test18.bas similarity index 100% rename from lang/basic/test/test18.b rename to lang/basic/test/test18.bas diff --git a/lang/basic/test/test19.b b/lang/basic/test/test19.bas similarity index 100% rename from lang/basic/test/test19.b rename to lang/basic/test/test19.bas diff --git a/lang/basic/test/test20.b b/lang/basic/test/test20.bas similarity index 100% rename from lang/basic/test/test20.b rename to lang/basic/test/test20.bas diff --git a/lang/basic/test/test21.b b/lang/basic/test/test21.bas similarity index 100% rename from lang/basic/test/test21.b rename to lang/basic/test/test21.bas diff --git a/lang/basic/test/test22.b b/lang/basic/test/test22.bas similarity index 100% rename from lang/basic/test/test22.b rename to lang/basic/test/test22.bas diff --git a/lang/basic/test/test23.b b/lang/basic/test/test23.bas similarity index 100% rename from lang/basic/test/test23.b rename to lang/basic/test/test23.bas diff --git a/lang/basic/test/test24.b b/lang/basic/test/test24.bas similarity index 100% rename from lang/basic/test/test24.b rename to lang/basic/test/test24.bas diff --git a/lang/basic/test/test25.b b/lang/basic/test/test25.bas similarity index 100% rename from lang/basic/test/test25.b rename to lang/basic/test/test25.bas diff --git a/lang/basic/test/test26.b b/lang/basic/test/test26.bas similarity index 100% rename from lang/basic/test/test26.b rename to lang/basic/test/test26.bas diff --git a/lang/basic/test/test27.b b/lang/basic/test/test27.bas similarity index 100% rename from lang/basic/test/test27.b rename to lang/basic/test/test27.bas diff --git a/lang/basic/test/test28.b b/lang/basic/test/test28.bas similarity index 100% rename from lang/basic/test/test28.b rename to lang/basic/test/test28.bas diff --git a/lang/basic/test/test29.b b/lang/basic/test/test29.bas similarity index 100% rename from lang/basic/test/test29.b rename to lang/basic/test/test29.bas diff --git a/lang/basic/test/test30.b b/lang/basic/test/test30.bas similarity index 100% rename from lang/basic/test/test30.b rename to lang/basic/test/test30.bas diff --git a/lang/basic/test/test31.b b/lang/basic/test/test31.bas similarity index 100% rename from lang/basic/test/test31.b rename to lang/basic/test/test31.bas diff --git a/lang/basic/test/test32.b b/lang/basic/test/test32.bas similarity index 100% rename from lang/basic/test/test32.b rename to lang/basic/test/test32.bas diff --git a/lang/basic/test/test33.b b/lang/basic/test/test33.bas similarity index 100% rename from lang/basic/test/test33.b rename to lang/basic/test/test33.bas diff --git a/lang/basic/test/test34.b b/lang/basic/test/test34.bas similarity index 100% rename from lang/basic/test/test34.b rename to lang/basic/test/test34.bas diff --git a/lang/basic/test/test35.b b/lang/basic/test/test35.bas similarity index 100% rename from lang/basic/test/test35.b rename to lang/basic/test/test35.bas diff --git a/lang/cem/libcc.ansi/build.lua b/lang/cem/libcc.ansi/build.lua index 601a50de4..20591f803 100644 --- a/lang/cem/libcc.ansi/build.lua +++ b/lang/cem/libcc.ansi/build.lua @@ -51,8 +51,8 @@ for _, plat in ipairs(vars.plats) do }, hdrs = {}, -- must be empty deps = { - "lang/cem/libcc.ansi/headers+headers", - "plat/"..plat.."/include+headers", + "lang/cem/libcc.ansi/headers+pkg", + "plat/"..plat.."/include+pkg", "./malloc/malloc.h", "./math/localmath.h", "./stdio/loc_incl.h", diff --git a/lang/m2/comp/build.lua b/lang/m2/comp/build.lua index 95c4a30d7..4e12d24f7 100644 --- a/lang/m2/comp/build.lua +++ b/lang/m2/comp/build.lua @@ -113,6 +113,7 @@ cprogram { "h+emheaders", "modules+headers", "modules/src/alloc+lib", + "modules/src/data+lib", "modules/src/em_code+lib_k", "modules/src/em_data+lib", "modules/src/em_mes+lib", diff --git a/lang/m2/comp/defmodule.c b/lang/m2/comp/defmodule.c index f26168a28..0ecb1dd2a 100644 --- a/lang/m2/comp/defmodule.c +++ b/lang/m2/comp/defmodule.c @@ -9,48 +9,50 @@ /* $Id$ */ +#include "debug.h" #include "parameters.h" -#include "debug.h" +#include +#include +#include +#include #include -#include -#include -#include -#include +#include -#include "idf.h" -#include "input.h" -#include "scope.h" -#include "LLlex.h" -#include "def.h" -#include "Lpars.h" -#include "f_info.h" -#include "main.h" -#include "node.h" -#include "type.h" -#include "misc.h" +#include "LLlex.h" +#include "Lpars.h" +#include "def.h" +#include "f_info.h" +#include "idf.h" +#include "input.h" +#include "main.h" +#include "misc.h" +#include "node.h" +#include "scope.h" +#include "type.h" #ifdef DEBUG -long sys_filesize(); +long sys_filesize(); #endif -t_idf *DefId; +t_idf* DefId; -char * -getwdir(fn) - register char *fn; +char* + getwdir(fn) register char* fn; { - register char *p; - char *strrchr(); + register char* p; + char* strrchr(); - while ((p = strrchr(fn,'/')) && *(p + 1) == '\0') { + while ((p = strrchr(fn, '/')) && *(p + 1) == '\0') + { /* remove trailing /'s */ *p = '\0'; } - if (p) { + if (p) + { *p = '\0'; - fn = Salloc(fn, (unsigned) (p - &fn[0] + 1)); + fn = Salloc(fn, (unsigned)(p - &fn[0] + 1)); *p = '/'; return fn; } @@ -58,20 +60,15 @@ getwdir(fn) } STATIC -GetFile(name) - char *name; +GetFile(name) char* name; { /* Try to find a file with basename "name" and extension ".def", in the directories mentioned in "DEFPATH". */ - char buf[15]; - char *strncpy(), *strcat(); - - strncpy(buf, name, 10); - buf[10] = '\0'; /* maximum length */ - strcat(buf, ".def"); + char* buf = aprintf("%s.def", name); DEFPATH[0] = WorkingDir; - if (! InsertFile(buf, DEFPATH, &(FileName))) { + if (!InsertFile(buf, DEFPATH, &(FileName))) + { error("could not find a DEFINITION MODULE for \"%s\"", name); return 0; } @@ -81,25 +78,25 @@ GetFile(name) return 1; } -t_def * -GetDefinitionModule(id, incr) - register t_idf *id; +t_def* + GetDefinitionModule(id, incr) register t_idf* id; { /* Return a pointer to the "def" structure of the definition module indicated by "id". We may have to read the definition module itself. Also increment level by "incr". */ - register t_def *df; + register t_def* df; static int level; - t_scopelist *vis; - char *fn = FileName; + t_scopelist* vis; + char* fn = FileName; int ln = LineNumber; - t_scope *newsc; + t_scope* newsc; level += incr; df = lookup(id, GlobalScope, D_IMPORTED, 0); - if (!df) { + if (!df) + { /* Read definition module. Make an exception for SYSTEM. */ extern int ForeignFlag; @@ -110,53 +107,62 @@ GetDefinitionModule(id, incr) newsc = CurrentScope; vis = CurrVis; newsc->sc_defmodule = incr; - if (!strcmp(id->id_text, "SYSTEM")) { + if (!strcmp(id->id_text, "SYSTEM")) + { do_SYSTEM(); df = lookup(id, GlobalScope, D_IMPORTED, 0); } - else { - if (!is_anon_idf(id) && GetFile(id->id_text)) { + else + { + if (!is_anon_idf(id) && GetFile(id->id_text)) + { - char *f = FileName; + char* f = FileName; DefModule(); df = lookup(id, GlobalScope, D_IMPORTED, 0); - if (level == 1 && - (df && !(df->df_flags & D_FOREIGN))) { + if (level == 1 && (df && !(df->df_flags & D_FOREIGN))) + { /* The module is directly imported by the currently defined module, and is not foreign, so we have to remember its name because we have to call its initialization routine */ - static t_node *nd_end; - register t_node *n; - extern t_node *Modules; + static t_node* nd_end; + register t_node* n; + extern t_node* Modules; n = dot2leaf(Def); n->nd_def = newsc->sc_definedby; - if (nd_end) nd_end->nd_NEXT = n; - else Modules = n; + if (nd_end) + nd_end->nd_NEXT = n; + else + Modules = n; nd_end = n; } free(f); } - else { + else + { df = lookup(id, GlobalScope, D_IMPORTED, 0); newsc->sc_name = id->id_text; } } close_scope(SC_CHKFORW); - if (! df) { + if (!df) + { df = MkDef(id, GlobalScope, D_ERROR); df->mod_vis = vis; newsc->sc_definedby = df; } } - else if (df->df_flags & D_BUSY) { + else if (df->df_flags & D_BUSY) + { error("definition module \"%s\" depends on itself", - id->id_text); + id->id_text); } - else if (df == Defined && level == 1) { + else if (df == Defined && level == 1) + { error("cannot import from current module \"%s\"", id->id_text); df->df_kind = D_ERROR; } diff --git a/lang/m2/comp/em_m2.6 b/lang/m2/comp/em_m2.6 index a122a4a30..dfe41a3df 100644 --- a/lang/m2/comp/em_m2.6 +++ b/lang/m2/comp/em_m2.6 @@ -1,10 +1,10 @@ -.TH EM_M2 6 "$Revision$" +.TH EM_M2 6 2017-01-18 .ad .SH NAME em_m2 \- ACK Modula\-2 compiler .SH SYNOPSIS .B ~em/lib.bin/em_m2 -.RI [ option ] +.RI [ option ] .I source .I destination .SH DESCRIPTION @@ -15,9 +15,9 @@ into EM code. The input is taken from .IR source , while the -EM code is written on +EM code is written on .IR destination . -.br +.PP .I Option is a, possibly empty, sequence of the following combinations: .IP \fB\-I\fIdirname\fR @@ -65,7 +65,8 @@ make all procedure names global, so that \fIadb\fR(1) understands them. .IP \fB\-g\fR produce a DBX-style symbol table. .IP \fB\-l\fR -enable local extensions. Currently, there are two local extensions: +enable local extensions. +Currently, there are two local extensions: procedure constants, and the type LONGCARD. .IP \fB\-s\fR make INTEGER ranges symmetric, t.i., MIN(INTEGER) = - MAX(INTEGER). @@ -77,11 +78,11 @@ disable all range checks. enable extra array bound checks, for machines that do not implement the EM ones. .IP \fB-U\fR -allow for underscores within identifiers. Identifiers may not start with +allow for underscores within identifiers. +Identifiers may not start with an underscore, even if this flag is given. .IP \fB-3\fR only accept Modula-2 programs that strictly conform to [1]. -.LP .SH SEE ALSO \fIack\fR(1), \fImodula-2\fR(1) .IP [1] diff --git a/lang/m2/comp/modula-2.1 b/lang/m2/comp/modula-2.1 index 206d33bb7..ee9bc94bd 100644 --- a/lang/m2/comp/modula-2.1 +++ b/lang/m2/comp/modula-2.1 @@ -19,11 +19,6 @@ Implementation modules and program modules must reside in files having a .PP The name of the file in which a definition module is stored must be the same as the module-name, apart from the extension. -Also, in most Unix systems filenames are only 14 characters long. -So, given an IMPORT declaration for a module called "LongModulName", -the compiler will try to open a file called "LongModulN.def". -The requirement does not hold for implementation or program modules, -but is certainly recommended. .SH CALLING THE COMPILER The easiest way to do this is to let the \fIack\fR(1) program do it. So, to compile a program module "prog.mod", just call diff --git a/lang/m2/comp/walk.c b/lang/m2/comp/walk.c index 93cc3308b..b36dbc8f0 100644 --- a/lang/m2/comp/walk.c +++ b/lang/m2/comp/walk.c @@ -13,71 +13,72 @@ code for these parts. */ -#include -#include +#include +#include #include "parameters.h" -#include "debug.h" +#include "debug.h" -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "LLlex.h" -#include "def.h" -#include "type.h" -#include "scope.h" -#include "main.h" -#include "node.h" -#include "Lpars.h" -#include "desig.h" -#include "f_info.h" -#include "idf.h" -#include "chk_expr.h" -#include "walk.h" -#include "misc.h" -#include "warning.h" +#include "LLlex.h" +#include "def.h" +#include "type.h" +#include "scope.h" +#include "main.h" +#include "node.h" +#include "Lpars.h" +#include "desig.h" +#include "f_info.h" +#include "idf.h" +#include "chk_expr.h" +#include "walk.h" +#include "misc.h" +#include "warning.h" -extern arith NewPtr(); -extern arith NewInt(); -extern arith TmpSpace(); +extern arith NewPtr(); +extern arith NewInt(); +extern arith TmpSpace(); -extern int proclevel; -extern int gdb_flag; +extern int proclevel; +extern int gdb_flag; -label text_label; -label data_label = 1; -struct withdesig *WithDesigs; -t_node *Modules; +label text_label; +label data_label = 1; +struct withdesig* WithDesigs; +t_node* Modules; -static t_type *func_type; -static t_node *priority; -static int oldlineno; +static t_type* func_type; +static t_node* priority; +static int oldlineno; -static int RegisterMessage(); -static int WalkDef(); +static int RegisterMessage(); +static int WalkDef(); #ifdef DBSYMTAB -static int stabdef(); +static int stabdef(); #endif -static int MkCalls(); -static void UseWarnings(); +static int MkCalls(); +static void UseWarnings(); -#define NO_EXIT_LABEL ((label) 0) -#define RETURN_LABEL ((label) 1) +#define NO_EXIT_LABEL ((label)0) +#define RETURN_LABEL ((label)1) -#define REACH_FLAG 1 -#define EXIT_FLAG 2 +#define REACH_FLAG 1 +#define EXIT_FLAG 2 void DoAssign(); int -LblWalkNode(lbl, nd, exit, reach) - label lbl, exit; - t_node *nd; + LblWalkNode(lbl, nd, exit, reach) + label lbl, + exit; +t_node* nd; { /* Generate code for node "nd", after generating instruction label "lbl". "exit" is the exit label for the closest @@ -96,10 +97,11 @@ DoPriority() /* For the time being (???), handle priorities by calls to the runtime system */ - if (priority) { + if (priority) + { tmpprio = NewInt(); C_loc(priority->nd_INT); - CAL("stackprio", (int) word_size); + CAL("stackprio", (int)word_size); C_lfr(word_size); C_stl(tmpprio); } @@ -108,15 +110,16 @@ DoPriority() STATIC EndPriority() { - if (priority) { + if (priority) + { C_lol(tmpprio); - CAL("unstackprio", (int) word_size); + CAL("unstackprio", (int)word_size); FreeInt(tmpprio); } } def_ilb(l) - label l; + label l; { /* Instruction label definition. Forget about line number. */ @@ -124,27 +127,29 @@ def_ilb(l) oldlineno = 0; } -DoLineno(nd) - register t_node *nd; +DoLineno(nd) register t_node* nd; { /* Generate line number information, if necessary. */ - if ((! options['L'] + if ((!options['L'] #ifdef DBSYMTAB - || options['g'] + || options['g'] #endif /* DBSYMTAB */ - ) && - nd->nd_lineno && - nd->nd_lineno != oldlineno) { + ) + && nd->nd_lineno && nd->nd_lineno != oldlineno) + { oldlineno = nd->nd_lineno; - if (! options['L']) C_lin((arith) nd->nd_lineno); + if (!options['L']) + C_lin((arith)nd->nd_lineno); #ifdef DBSYMTAB - if ( options['g']) { - static int ms_lineno; + if (options['g']) + { + static int ms_lineno; - if (ms_lineno != nd->nd_lineno) { + if (ms_lineno != nd->nd_lineno) + { ms_lineno = nd->nd_lineno; - C_ms_std((char *) 0, N_SLINE, ms_lineno); + C_ms_std((char*)0, N_SLINE, ms_lineno); } } #endif /* DBSYMTAB */ @@ -158,30 +163,31 @@ DoFilename(needed) procedure entry, and after generating a call to another procedure. */ - static label filename_label = 0; + static label filename_label = 0; - oldlineno = 0; /* always invalidate remembered line number */ - if (needed && ! options['L']) { + oldlineno = 0; /* always invalidate remembered line number */ + if (needed && !options['L']) + { - if (! filename_label) { + if (!filename_label) + { filename_label = 1; - C_df_dlb((label) 1); - C_rom_scon(FileName, (arith) (strlen(FileName) + 1)); + C_df_dlb((label)1); + C_rom_scon(FileName, (arith)(strlen(FileName) + 1)); } - C_fil_dlb((label) 1, (arith) 0); + C_fil_dlb((label)1, (arith)0); } } -WalkModule(module) - register t_def *module; +WalkModule(module) register t_def* module; { /* Walk through a module, and all its local definitions. Also generate code for its body. This code is collected in an initialization routine. */ - register t_scope *sc; - t_scopelist *savevis = CurrVis; + register t_scope* sc; + t_scopelist* savevis = CurrVis; CurrVis = module->mod_vis; priority = module->mod_priority; @@ -195,52 +201,58 @@ WalkModule(module) First call initialization routines for modules defined within this module. */ - sc->sc_off = 0; /* no locals (yet) */ - text_label = 1; /* label at end of initialization routine */ - TmpOpen(sc); /* Initialize for temporaries */ + sc->sc_off = 0; /* no locals (yet) */ + text_label = 1; /* label at end of initialization routine */ + TmpOpen(sc); /* Initialize for temporaries */ C_pro_narg(sc->sc_name); #ifdef DBSYMTAB - if (options['g']) { + if (options['g']) + { stb_string(module, D_MODULE); WalkDefList(sc->sc_def, stabdef); - if (state == PROGRAM && module == Defined) { + if (state == PROGRAM && module == Defined) + { C_ms_stb_cst(module->df_idf->id_text, - N_MAIN, - 0, - (arith) 0); + N_MAIN, + 0, + (arith)0); } stb_string(module, D_END); } #endif DoPriority(); - if (module == Defined) { + if (module == Defined) + { /* Body of implementation or program module. Call initialization routines of imported modules. Also prevent recursive calls of this one. */ - register t_node *nd = Modules; + register t_node* nd = Modules; - if (state == IMPLEMENTATION) { + if (state == IMPLEMENTATION) + { /* We don't actually prevent recursive calls, but do nothing if called recursively */ C_df_dlb(++data_label); - C_con_cst((arith) 0); + C_con_cst((arith)0); /* if this one is set to non-zero, the initialization was already done. */ - C_loe_dlb(data_label, (arith) 0); + C_loe_dlb(data_label, (arith)0); C_zne(RETURN_LABEL); - C_ine_dlb(data_label, (arith) 0); + C_ine_dlb(data_label, (arith)0); } - else if (! options['R']) { + else if (!options['R']) + { /* put funny value in BSS, in an attempt to detect uninitialized variables */ C_cal("killbss"); } - for (; nd; nd = nd->nd_NEXT) { + for (; nd; nd = nd->nd_NEXT) + { C_cal(nd->nd_def->mod_vis->sc_scope->sc_name); } DoFilename(1); @@ -248,18 +260,20 @@ WalkModule(module) WalkDefList(sc->sc_def, MkCalls); proclevel++; #ifdef DBSYMTAB - if (options['g']) { - C_ms_std((char *) 0, N_LBRAC, gdb_flag ? 0 : proclevel); + if (options['g']) + { + C_ms_std((char*)0, N_LBRAC, gdb_flag ? 0 : proclevel); } #endif /* DBSYMTAB */ WalkNode(module->mod_body, NO_EXIT_LABEL, REACH_FLAG); DO_DEBUG(options['X'], PrNode(module->mod_body, 0)); def_ilb(RETURN_LABEL); EndPriority(); - C_ret((arith) 0); + C_ret((arith)0); #ifdef DBSYMTAB - if (options['g']) { - C_ms_std((char *) 0, N_RBRAC, gdb_flag ? 0 : proclevel); + if (options['g']) + { + C_ms_std((char*)0, N_RBRAC, gdb_flag ? 0 : proclevel); } #endif /* DBSYMTAB */ C_end(-sc->sc_off); @@ -270,19 +284,18 @@ WalkModule(module) WalkDefList(sc->sc_def, UseWarnings); } -WalkProcedure(procedure) - register t_def *procedure; +WalkProcedure(procedure) register t_def* procedure; { /* Walk through the definition of a procedure and all its local definitions, checking and generating code. */ - t_scopelist *savevis = CurrVis; - register t_type *tp; - register t_param *param; - register t_scope *procscope = procedure->prc_vis->sc_scope; - label too_big = 0; /* returnsize larger than returnarea */ - arith StackAdjustment = 0; /* space for conformant arrays */ - arith retsav = 0; /* temporary space for return value */ + t_scopelist* savevis = CurrVis; + register t_type* tp; + register t_param* param; + register t_scope* procscope = procedure->prc_vis->sc_scope; + label too_big = 0; /* returnsize larger than returnarea */ + arith StackAdjustment = 0; /* space for conformant arrays */ + arith retsav = 0; /* temporary space for return value */ arith func_res_size = 0; #ifdef USE_INSERT int partno = C_getid(); @@ -301,9 +314,11 @@ WalkProcedure(procedure) func_type = tp = RemoveEqual(ResultType(procedure->df_type)); - if (tp) { + if (tp) + { func_res_size = WA(tp->tp_size); - if (TooBigForReturnArea(tp)) { + if (TooBigForReturnArea(tp)) + { #ifdef BIG_RESULT_ON_STACK /* The result type of this procedure is too big. The caller will have reserved space on its stack, @@ -330,22 +345,23 @@ WalkProcedure(procedure) */ TmpOpen(procscope); #ifdef USE_INSERT - C_insertpart(partno2); /* procedure header */ + C_insertpart(partno2); /* procedure header */ #else C_pro_narg(procedure->prc_name); #ifdef DBSYMTAB - if (options['g']) { + if (options['g']) + { stb_string(procedure, D_PROCEDURE); WalkDefList(procscope->sc_def, stabdef); stb_string(procedure, D_PEND); - C_ms_std((char *) 0, N_LBRAC, gdb_flag ? 0 : proclevel); + C_ms_std((char*)0, N_LBRAC, gdb_flag ? 0 : proclevel); } #endif /* DBSYMTAB */ C_ms_par(procedure->df_type->prc_nbpar #ifdef BIG_RESULT_ON_STACK - + (too_big ? func_res_size : 0) + + (too_big ? func_res_size : 0) #endif - ); + ); #endif /* generate code for filename only when the procedure can be exported, either directly or by taking the address. @@ -355,27 +371,31 @@ WalkProcedure(procedure) DoFilename(procscope->sc_level == 1); DoPriority(); - text_label = 1; /* label at end of procedure */ + text_label = 1; /* label at end of procedure */ /* Check if we must save the stack pointer */ for (param = ParamList(procedure->df_type); param; - param = param->par_next) { - if (! IsVarParam(param)) { + param = param->par_next) + { + if (!IsVarParam(param)) + { tp = TypeOfParam(param); - if ( IsConformantArray(tp)) { + if (IsConformantArray(tp)) + { /* First time we get here */ - if (func_type && !too_big) { + if (func_type && !too_big) + { /* Some local space, only needed if the value itself is returned */ - retsav= TmpSpace(func_res_size, 1); + retsav = TmpSpace(func_res_size, 1); } StackAdjustment = NewPtr(); - C_lor((arith) 1); + C_lor((arith)1); STL(StackAdjustment, pointer_size); } } @@ -390,12 +410,14 @@ WalkProcedure(procedure) def_ilb(cd_body); #endif - if ((WalkNode(procedure->prc_body, NO_EXIT_LABEL, REACH_FLAG) & REACH_FLAG)) { - if (func_res_size) { + if ((WalkNode(procedure->prc_body, NO_EXIT_LABEL, REACH_FLAG) & REACH_FLAG)) + { + if (func_res_size) + { node_warning(procscope->sc_end, - W_ORDINARY, - "function procedure \"%s\" does not always return a value", - procedure->df_idf->id_text); + W_ORDINARY, + "function procedure \"%s\" does not always return a value", + procedure->df_idf->id_text); c_loc(M2_NORESULT); C_trp(); C_asp(-func_res_size); @@ -422,13 +444,16 @@ WalkProcedure(procedure) */ for (param = ParamList(procedure->df_type); param; - param = param->par_next) { - if (! IsVarParam(param)) { + param = param->par_next) + { + if (!IsVarParam(param)) + { tp = TypeOfParam(param); - if (! IsConformantArray(tp)) { - if (tp->tp_size < word_size && - (int) word_size % (int) tp->tp_size == 0) { + if (!IsConformantArray(tp)) + { + if (tp->tp_size < word_size && (int)word_size % (int)tp->tp_size == 0) + { C_lol(param->par_def->var_off); STL(param->par_def->var_off, tp->tp_size); @@ -450,11 +475,11 @@ WalkProcedure(procedure) CAL("new_stackptr", (int)pointer_size); C_lfr(pointer_size); C_ass(pointer_size); - /* adjusted stack pointer */ + /* adjusted stack pointer */ LOL(param->par_def->var_off, pointer_size); - /* push source address */ + /* push source address */ CAL("copy_array", (int)pointer_size); - /* copy */ + /* copy */ } } #ifdef USE_INSERT @@ -463,9 +488,10 @@ WalkProcedure(procedure) c_bra(cd_body); #endif DO_DEBUG(options['X'], PrNode(procedure->prc_body, 0)); - def_ilb(RETURN_LABEL); /* label at end */ - if (too_big) { - /* Fill the data area reserved for the function result + def_ilb(RETURN_LABEL); /* label at end */ + if (too_big) + { +/* Fill the data area reserved for the function result with the result */ #ifdef BIG_RESULT_ON_STACK @@ -474,11 +500,12 @@ WalkProcedure(procedure) c_lae_dlb(too_big); #endif /* BIG_RESULT_ON_STACK */ C_sti(func_res_size); - if (StackAdjustment) { + if (StackAdjustment) + { /* Remove copies of conformant arrays */ LOL(StackAdjustment, pointer_size); - C_str((arith) 1); + C_str((arith)1); } #ifdef BIG_RESULT_ON_STACK func_res_size = 0; @@ -487,17 +514,20 @@ WalkProcedure(procedure) func_res_size = pointer_size; #endif /* BIG_RESULT_ON_STACK */ } - else if (StackAdjustment) { + else if (StackAdjustment) + { /* First save the function result in a safe place. Then remove copies of conformant arrays, and put function result back on the stack */ - if (func_type) { + if (func_type) + { STL(retsav, func_res_size); } LOL(StackAdjustment, pointer_size); - C_str((arith) 1); - if (func_type) { + C_str((arith)1); + if (func_type) + { LOL(retsav, func_res_size); } } @@ -507,32 +537,36 @@ WalkProcedure(procedure) C_beginpart(partno2); C_pro(procedure->prc_name, -procscope->sc_off); #ifdef DBSYMTAB - if (options['g']) { + if (options['g']) + { stb_string(procedure, D_PROCEDURE); WalkDefList(procscope->sc_def, stabdef); stb_string(procedure, D_PEND); - C_ms_std((char *) 0, N_LBRAC, gdb_flag ? 0 : proclevel); + C_ms_std((char*)0, N_LBRAC, gdb_flag ? 0 : proclevel); } #endif /* DBSYMTAB */ C_ms_par(procedure->df_type->prc_nbpar #ifdef BIG_RESULT_ON_STACK - + (too_big ? func_res_size : 0) + + (too_big ? func_res_size : 0) #endif - ); + ); #endif - if (! options['n']) WalkDefList(procscope->sc_def, RegisterMessage); + if (!options['n']) + WalkDefList(procscope->sc_def, RegisterMessage); #ifdef USE_INSERT C_endpart(partno2); #endif #ifdef DBSYMTAB - if (options['g']) { - C_ms_std((char *) 0, N_RBRAC, gdb_flag ? 0 : proclevel); + if (options['g']) + { + C_ms_std((char*)0, N_RBRAC, gdb_flag ? 0 : proclevel); } #endif /* DBSYMTAB */ C_end(-procscope->sc_off); - if (! fit(procscope->sc_off, (int) word_size)) { + if (!fit(procscope->sc_off, (int)word_size)) + { node_error(procedure->prc_body, - "maximum local byte count exceeded"); + "maximum local byte count exceeded"); } TmpClose(); CurrVis = savevis; @@ -540,50 +574,48 @@ WalkProcedure(procedure) WalkDefList(procscope->sc_def, UseWarnings); } -static -WalkDef(df) - register t_def *df; +static WalkDef(df) register t_def* df; { /* Walk through a list of definitions */ - switch(df->df_kind) { - case D_MODULE: - WalkModule(df); - break; - case D_PROCEDURE: - WalkProcedure(df); - break; - case D_VARIABLE: - if (!proclevel && !(df->df_flags & D_ADDRGIVEN)) { - C_df_dnam(df->var_name); - C_bss_cst( - WA(df->df_type->tp_size), - (arith) 0, 0); - } - break; - default: - /* nothing */ - ; + switch (df->df_kind) + { + case D_MODULE: + WalkModule(df); + break; + case D_PROCEDURE: + WalkProcedure(df); + break; + case D_VARIABLE: + if (!proclevel && !(df->df_flags & D_ADDRGIVEN)) + { + C_df_dnam(df->var_name); + C_bss_cst( + WA(df->df_type->tp_size), + (arith)0, 0); + } + break; + default: + /* nothing */ + ; } } -static -MkCalls(df) - register t_def *df; +static MkCalls(df) register t_def* df; { /* Generate calls to initialization routines of modules */ - if (df->df_kind == D_MODULE) { - C_lxl((arith) 0); + if (df->df_kind == D_MODULE) + { + C_lxl((arith)0); CAL(df->mod_vis->sc_scope->sc_name, (int)pointer_size); } } -WalkLink(nd, exit_label, end_reached) - register t_node *nd; - label exit_label; +WalkLink(nd, exit_label, end_reached) register t_node* nd; +label exit_label; { /* Walk node "nd", which is a link. "exit_label" is set to a label number when inside a LOOP. @@ -591,7 +623,8 @@ WalkLink(nd, exit_label, end_reached) and whether an EXIT statement was seen (EXIT_FLAG). */ - while (nd && nd->nd_class == Link) { /* statement list */ + while (nd && nd->nd_class == Link) + { /* statement list */ end_reached = WalkNode(nd->nd_LEFT, exit_label, end_reached); nd = nd->nd_RIGHT; } @@ -600,85 +633,94 @@ WalkLink(nd, exit_label, end_reached) } STATIC -ForLoopVarExpr(nd) - register t_node *nd; +ForLoopVarExpr(nd) register t_node* nd; { - register t_type *tp = nd->nd_type; + register t_type* tp = nd->nd_type; CodePExpr(nd); CodeCoercion(tp, BaseType(tp)); } int -WalkStat(nd, exit_label, end_reached) - register t_node *nd; - label exit_label; + WalkStat(nd, exit_label, end_reached) register t_node* nd; +label exit_label; { /* Walk through a statement, generating code for it. */ - register t_node *left = nd->nd_LEFT; - register t_node *right = nd->nd_RIGHT; + register t_node* left = nd->nd_LEFT; + register t_node* right = nd->nd_RIGHT; assert(nd->nd_class == Stat); - if (nd->nd_symb == ';') return 1; + if (nd->nd_symb == ';') + return 1; - if (! end_reached & REACH_FLAG) { + if (!end_reached & REACH_FLAG) + { node_warning(nd, W_ORDINARY, "statement not reached"); } - if (nd->nd_symb != WHILE || - nd->nd_lineno != left->nd_lineno) { + if (nd->nd_symb != WHILE || nd->nd_lineno != left->nd_lineno) + { /* Avoid double linenumber generation in while statements */ DoLineno(nd); } options['R'] = (nd->nd_flags & ROPTION); options['A'] = (nd->nd_flags & AOPTION); - switch(nd->nd_symb) { - case '(': { - t_node *nd1 = nd; - if (ChkCall(&nd1)) { - assert(nd == nd1); - if (nd->nd_type != 0) { - node_error(nd, "procedure call expected instead of function call"); - break; + switch (nd->nd_symb) + { + case '(': + { + t_node* nd1 = nd; + if (ChkCall(&nd1)) + { + assert(nd == nd1); + if (nd->nd_type != 0) + { + node_error(nd, "only proper procedures can be called from top-level " + "statement; this is a function procedure"); + break; + } + CodeCall(nd); } - CodeCall(nd); - } } break; - case BECOMES: - DoAssign(nd); - break; + case BECOMES: + DoAssign(nd); + break; - case IF: - { label l1 = ++text_label, l3 = ++text_label; + case IF: + { + label l1 = ++text_label, l3 = ++text_label; int end_r; ExpectBool(&(nd->nd_LEFT), l3, l1); assert(right->nd_symb == THEN); end_r = LblWalkNode(l3, right->nd_LEFT, exit_label, end_reached); - if (right->nd_RIGHT) { /* ELSE part */ + if (right->nd_RIGHT) + { /* ELSE part */ label l2 = ++text_label; c_bra(l2); end_reached = end_r | LblWalkNode(l1, right->nd_RIGHT, exit_label, end_reached); l1 = l2; } - else end_reached |= end_r; + else + end_reached |= end_r; def_ilb(l1); break; } - case CASE: - end_reached = CaseCode(nd, exit_label, end_reached); - break; + case CASE: + end_reached = CaseCode(nd, exit_label, end_reached); + break; - case WHILE: - { label loop = ++text_label, - exit = ++text_label, - dummy = ++text_label; + case WHILE: + { + label loop = ++text_label, + exit = ++text_label, + dummy = ++text_label; c_bra(dummy); end_reached |= LblWalkNode(loop, right, exit_label, end_reached); @@ -688,8 +730,9 @@ WalkStat(nd, exit_label, end_reached) break; } - case REPEAT: - { label loop = ++text_label, exit = ++text_label; + case REPEAT: + { + label loop = ++text_label, exit = ++text_label; end_reached = LblWalkNode(loop, left, exit_label, end_reached); ExpectBool(&(nd->nd_RIGHT), exit, loop); @@ -697,19 +740,22 @@ WalkStat(nd, exit_label, end_reached) break; } - case LOOP: - { label loop = ++text_label, exit = ++text_label; + case LOOP: + { + label loop = ++text_label, exit = ++text_label; - if (LblWalkNode(loop, right, exit, end_reached) & EXIT_FLAG) { + if (LblWalkNode(loop, right, exit, end_reached) & EXIT_FLAG) + { end_reached &= REACH_FLAG; } - else end_reached = 0; + else + end_reached = 0; c_bra(loop); def_ilb(exit); break; } - case FOR: + case FOR: { arith tmp = NewInt(); arith tmp2 = NewInt(); @@ -718,17 +764,19 @@ WalkStat(nd, exit_label, end_reached) label l2 = ++text_label; int uns = 0; arith stepsize; - t_type *bstp; - t_node *loopid; + t_type* bstp; + t_node* loopid; good_forvar = DoForInit(left); loopid = left->nd_LEFT; - if ((stepsize = right->nd_LEFT->nd_INT) == 0) { + if ((stepsize = right->nd_LEFT->nd_INT) == 0) + { node_warning(right->nd_LEFT, - W_ORDINARY, - "zero stepsize in FOR loop"); + W_ORDINARY, + "zero stepsize in FOR loop"); } - if (good_forvar) { + if (good_forvar) + { bstp = BaseType(loopid->nd_type); uns = bstp->tp_fund != T_INTEGER; CodePExpr(left->nd_RIGHT->nd_RIGHT); @@ -737,37 +785,46 @@ WalkStat(nd, exit_label, end_reached) C_dup(int_size); C_stl(tmp2); C_lol(tmp); - if (uns) C_cmu(int_size); - else C_cmi(int_size); - if (stepsize >= 0) C_zgt(l2); - else C_zlt(l2); + if (uns) + C_cmu(int_size); + else + C_cmi(int_size); + if (stepsize >= 0) + C_zgt(l2); + else + C_zlt(l2); C_lol(tmp2); RangeCheck(loopid->nd_type, - left->nd_RIGHT->nd_LEFT->nd_type); + left->nd_RIGHT->nd_LEFT->nd_type); CodeDStore(loopid); - if (stepsize >= 0) { + if (stepsize >= 0) + { C_lol(tmp); ForLoopVarExpr(loopid); } - else { + else + { stepsize = -stepsize; ForLoopVarExpr(loopid); C_lol(tmp); } C_sbu(int_size); - if (stepsize) { + if (stepsize) + { C_loc(stepsize); C_dvu(int_size); } C_stl(tmp); loopid->nd_def->df_flags |= D_FORLOOP; def_ilb(l1); - if (! options['R']) { + if (!options['R']) + { ForLoopVarExpr(loopid); C_stl(tmp2); } end_reached |= WalkNode(right->nd_RIGHT, exit_label, end_reached); - if (! options['R']) { + if (!options['R']) + { label x = ++text_label; C_lol(tmp2); ForLoopVarExpr(loopid); @@ -778,7 +835,8 @@ WalkStat(nd, exit_label, end_reached) } loopid->nd_def->df_flags &= ~D_FORLOOP; FreeInt(tmp2); - if (stepsize) { + if (stepsize) + { C_lol(tmp); C_zeq(l2); C_lol(tmp); @@ -792,7 +850,8 @@ WalkStat(nd, exit_label, end_reached) CodeDStore(loopid); } } - else { + else + { end_reached |= WalkNode(right->nd_RIGHT, exit_label, end_reached); loopid->nd_def->df_flags &= ~D_FORLOOP; } @@ -802,15 +861,17 @@ WalkStat(nd, exit_label, end_reached) } break; - case WITH: + case WITH: { t_scopelist link; struct withdesig wds; t_desig ds; - if (! WalkDesignator(&(nd->nd_LEFT), &ds, D_USED)) break; + if (!WalkDesignator(&(nd->nd_LEFT), &ds, D_USED)) + break; left = nd->nd_LEFT; - if (left->nd_type->tp_fund != T_RECORD) { + if (left->nd_type->tp_fund != T_RECORD) + { node_error(left, "record variable expected"); break; } @@ -836,44 +897,50 @@ WalkStat(nd, exit_label, end_reached) CurrVis = link.sc_next; WithDesigs = wds.w_next; FreePtr(ds.dsg_offset); - ChkDesig(&(nd->nd_LEFT), wds.w_flags & (D_USED|D_DEFINED)); + ChkDesig(&(nd->nd_LEFT), wds.w_flags & (D_USED | D_DEFINED)); break; } - case EXIT: - assert(exit_label != 0); + case EXIT: + assert(exit_label != 0); - if (end_reached & REACH_FLAG) end_reached = EXIT_FLAG; - c_bra(exit_label); - break; + if (end_reached & REACH_FLAG) + end_reached = EXIT_FLAG; + c_bra(exit_label); + break; - case RETURN: - end_reached &= ~REACH_FLAG; - if (right) { - if (! ChkExpression(&(nd->nd_RIGHT))) break; - /* The type of the return-expression must be + case RETURN: + end_reached &= ~REACH_FLAG; + if (right) + { + if (!ChkExpression(&(nd->nd_RIGHT))) + break; + /* The type of the return-expression must be assignment compatible with the result type of the function procedure (See Rep. 9.11). */ - if (!ChkAssCompat(&(nd->nd_RIGHT), func_type, "RETURN")) { - break; + if (!ChkAssCompat(&(nd->nd_RIGHT), func_type, "RETURN")) + { + break; + } + right = nd->nd_RIGHT; + if (right->nd_type->tp_fund == T_STRING) + { + CodePString(right, func_type); + } + else + CodePExpr(right); } - right = nd->nd_RIGHT; - if (right->nd_type->tp_fund == T_STRING) { - CodePString(right, func_type); - } - else CodePExpr(right); - } - c_bra(RETURN_LABEL); - break; + c_bra(RETURN_LABEL); + break; - default: - crash("(WalkStat)"); + default: + crash("(WalkStat)"); } return end_reached; } -extern int NodeCrash(); +extern int NodeCrash(); int (*WalkTable[])() = { NodeCrash, @@ -893,9 +960,8 @@ int (*WalkTable[])() = { extern t_desig null_desig; -ExpectBool(pnd, true_label, false_label) - register t_node **pnd; - label true_label, false_label; +ExpectBool(pnd, true_label, false_label) register t_node** pnd; +label true_label, false_label; { /* "pnd" must indicate a boolean expression. Check this and generate code to evaluate the expression. @@ -903,25 +969,27 @@ ExpectBool(pnd, true_label, false_label) t_desig ds; ds = null_desig; - if (ChkExpression(pnd)) { - if ((*pnd)->nd_type != bool_type && - (*pnd)->nd_type != error_type) { + if (ChkExpression(pnd)) + { + if ((*pnd)->nd_type != bool_type && (*pnd)->nd_type != error_type) + { node_error(*pnd, "boolean expression expected"); } - CodeExpr(*pnd, &ds, true_label, false_label); + CodeExpr(*pnd, &ds, true_label, false_label); } } int -WalkDesignator(pnd, ds, flags) - t_node **pnd; - t_desig *ds; + WalkDesignator(pnd, ds, flags) + t_node** pnd; +t_desig* ds; { /* Check designator and generate code for it */ - if (! ChkVariable(pnd, flags)) return 0; + if (!ChkVariable(pnd, flags)) + return 0; *ds = null_desig; CodeDesig(*pnd, ds); @@ -929,47 +997,54 @@ WalkDesignator(pnd, ds, flags) } DoForInit(nd) - t_node *nd; + t_node* nd; { - register t_node *right = nd->nd_RIGHT; - register t_def *df; - t_type *base_tp; + register t_node* right = nd->nd_RIGHT; + register t_def* df; + t_type* base_tp; t_type *tpl, *tpr; int r; - r = ChkVariable(&(nd->nd_LEFT), D_USED|D_DEFINED); + r = ChkVariable(&(nd->nd_LEFT), D_USED | D_DEFINED); r &= ChkExpression(&(right->nd_LEFT)); r &= ChkExpression(&(right->nd_RIGHT)); - if (!r) return 0; + if (!r) + return 0; df = nd->nd_LEFT->nd_def; - if (df->df_kind == D_FIELD) { + if (df->df_kind == D_FIELD) + { node_error(nd, - "FOR-loop variable may not be a field of a record"); + "FOR-loop variable may not be a field of a record"); return 1; } - if (!df->var_name && df->var_off >= 0) { + if (!df->var_name && df->var_off >= 0) + { node_error(nd, "FOR-loop variable may not be a parameter"); return 1; } - if (df->df_scope != CurrentScope) { - register t_scopelist *sc = CurrVis; + if (df->df_scope != CurrentScope) + { + register t_scopelist* sc = CurrVis; - for (;;) { - if (!sc) { + for (;;) + { + if (!sc) + { node_error(nd, - "FOR-loop variable may not be imported"); + "FOR-loop variable may not be imported"); return 1; } - if (sc->sc_scope == df->df_scope) break; + if (sc->sc_scope == df->df_scope) + break; sc = nextvisible(sc); } } - if (df->df_type->tp_size > word_size || - !(df->df_type->tp_fund & T_DISCRETE)) { + if (df->df_type->tp_size > word_size || !(df->df_type->tp_fund & T_DISCRETE)) + { node_error(nd, "illegal type of FOR loop variable"); return 1; } @@ -978,19 +1053,21 @@ DoForInit(nd) tpl = right->nd_LEFT->nd_type; tpr = right->nd_RIGHT->nd_type; #ifndef STRICT_3RD_ED - if (! options['3']) { - if (!ChkAssCompat(&(right->nd_LEFT), base_tp, "FOR statement") || - !ChkAssCompat(&(right->nd_RIGHT), base_tp, "FOR statement")) { - return 1; - } - if (!TstCompat(df->df_type, tpl) || - !TstCompat(df->df_type, tpr)) { -node_warning(nd, W_OLDFASHIONED, "compatibility required in FOR statement"); - } - } else + if (!options['3']) + { + if (!ChkAssCompat(&(right->nd_LEFT), base_tp, "FOR statement") || !ChkAssCompat(&(right->nd_RIGHT), base_tp, "FOR statement")) + { + return 1; + } + if (!TstCompat(df->df_type, tpl) || !TstCompat(df->df_type, tpr)) + { + node_warning(nd, W_OLDFASHIONED, "compatibility required in FOR statement"); + } + } + else #endif - if (!ChkCompat(&(right->nd_LEFT), base_tp, "FOR statement") || - !ChkCompat(&(right->nd_RIGHT), base_tp, "FOR statement")) { + if (!ChkCompat(&(right->nd_LEFT), base_tp, "FOR statement") || !ChkCompat(&(right->nd_RIGHT), base_tp, "FOR statement")) + { return 1; } @@ -998,8 +1075,7 @@ node_warning(nd, W_OLDFASHIONED, "compatibility required in FOR statement"); } void -DoAssign(nd) - register t_node *nd; + DoAssign(nd) register t_node* nd; { /* May we do it in this order (expression first) ??? The reference manual sais nothing about it, but the book does: @@ -1007,148 +1083,151 @@ DoAssign(nd) DAMN THE BOOK! */ t_desig dsr; - register t_type *tp; + register t_type* tp; - if (! (ChkExpression(&(nd->nd_RIGHT)) & - ChkVariable(&(nd->nd_LEFT), D_DEFINED))) return; + if (!(ChkExpression(&(nd->nd_RIGHT)) & ChkVariable(&(nd->nd_LEFT), D_DEFINED))) + return; tp = nd->nd_LEFT->nd_type; - if (! ChkAssCompat(&(nd->nd_RIGHT), tp, "assignment")) { + if (!ChkAssCompat(&(nd->nd_RIGHT), tp, "assignment")) + { return; } dsr = null_desig; -#define StackNeededFor(ds) ((ds).dsg_kind == DSG_PLOADED \ - || (ds).dsg_kind == DSG_INDEXED) +#define StackNeededFor(ds) ((ds).dsg_kind == DSG_PLOADED \ + || (ds).dsg_kind == DSG_INDEXED) CodeExpr(nd->nd_RIGHT, &dsr, NO_LABEL, NO_LABEL); tp = nd->nd_RIGHT->nd_type; - if (complex(tp)) { - if (StackNeededFor(dsr)) CodeAddress(&dsr); + if (complex(tp)) + { + if (StackNeededFor(dsr)) + CodeAddress(&dsr); } - else { + else + { CodeValue(&dsr, tp); } CodeMove(&dsr, nd->nd_LEFT, tp); } -static -RegisterMessage(df) - register t_def *df; +static RegisterMessage(df) register t_def* df; { - register t_type *tp; + register t_type* tp; - if (df->df_kind == D_VARIABLE) { - if ( !(df->df_flags & D_NOREG)) { + if (df->df_kind == D_VARIABLE) + { + if (!(df->df_flags & D_NOREG)) + { /* Examine type and size */ tp = BaseType(df->df_type); - if ((df->df_flags & D_VARPAR) || - (tp->tp_fund&(T_POINTER|T_HIDDEN|T_EQUAL))) { + if ((df->df_flags & D_VARPAR) || (tp->tp_fund & (T_POINTER | T_HIDDEN | T_EQUAL))) + { C_ms_reg(df->var_off, - pointer_size, - reg_pointer, - 0); + pointer_size, + reg_pointer, + 0); } - else if (tp->tp_fund & T_NUMERIC) { + else if (tp->tp_fund & T_NUMERIC) + { C_ms_reg(df->var_off, - tp->tp_size, - tp->tp_fund == T_REAL ? - reg_float : reg_any, - 0); + tp->tp_size, + tp->tp_fund == T_REAL ? reg_float : reg_any, + 0); } } } } static void -df_warning(nd, df, warning) - t_node *nd; - t_def *df; - char *warning; + df_warning(nd, df, warning) + t_node* nd; +t_def* df; +char* warning; { - if (! (df->df_kind & (D_VARIABLE|D_PROCEDURE|D_TYPE|D_CONST|D_PROCHEAD))) { + if (!(df->df_kind & (D_VARIABLE | D_PROCEDURE | D_TYPE | D_CONST | D_PROCHEAD))) + { return; } - if (warning) { + if (warning) + { node_warning(nd, - W_ORDINARY, - "%s \"%s\" %s", - (df->df_flags & D_VALPAR) ? "value parameter" : - (df->df_flags & D_VARPAR) ? "variable parameter" : - (df->df_kind == D_VARIABLE) ? "variable" : - (df->df_kind == D_TYPE) ? "type" : - (df->df_kind == D_CONST) ? "constant" : - "procedure", - df->df_idf->id_text, warning); + W_ORDINARY, + "%s \"%s\" %s", + (df->df_flags & D_VALPAR) ? "value parameter" : (df->df_flags & D_VARPAR) ? "variable parameter" : (df->df_kind == D_VARIABLE) ? "variable" : (df->df_kind == D_TYPE) ? "type" : (df->df_kind == D_CONST) ? "constant" : "procedure", + df->df_idf->id_text, warning); } } static void -UseWarnings(df) - register t_def *df; + UseWarnings(df) register t_def* df; { - t_node *nd = df->df_scope->sc_end; + t_node* nd = df->df_scope->sc_end; - if (is_anon_idf(df->df_idf) || - !(df->df_kind&(D_IMPORTED|D_VARIABLE|D_PROCEDURE|D_CONST|D_TYPE)) || - (df->df_flags&(D_EXPORTED|D_QEXPORTED))) { + if (is_anon_idf(df->df_idf) || !(df->df_kind & (D_IMPORTED | D_VARIABLE | D_PROCEDURE | D_CONST | D_TYPE)) || (df->df_flags & (D_EXPORTED | D_QEXPORTED))) + { return; } - if (df->df_kind & D_IMPORTED) { - register t_def *df1 = df->imp_def; + if (df->df_kind & D_IMPORTED) + { + register t_def* df1 = df->imp_def; - df1->df_flags |= df->df_flags & (D_USED|D_DEFINED); - if (df->df_kind == D_INUSE) return; - if ( !(df->df_flags & D_IMP_BY_EXP)) { - if (df->df_flags & (D_USED | D_DEFINED)) { + df1->df_flags |= df->df_flags & (D_USED | D_DEFINED); + if (df->df_kind == D_INUSE) + return; + if (!(df->df_flags & D_IMP_BY_EXP)) + { + if (df->df_flags & (D_USED | D_DEFINED)) + { return; } df_warning(nd, - df1, - df1->df_kind == D_VARIABLE ? - "imported but not used/assigned" : - "imported but not used"); + df1, + df1->df_kind == D_VARIABLE ? "imported but not used/assigned" : "imported but not used"); return; } df = df1; nd = df->df_scope->sc_end; } - switch(df->df_flags & (D_USED|D_DEFINED|D_VALPAR|D_VARPAR)) { - case 0: - case D_VARPAR: - df_warning(nd, df,"never used/assigned"); - break; - case D_USED: - df_warning(nd, df,"never assigned"); - break; - case D_VALPAR: - case D_DEFINED: - case D_DEFINED|D_VALPAR: - df_warning(nd, df,"never used"); - break; + switch (df->df_flags & (D_USED | D_DEFINED | D_VALPAR | D_VARPAR)) + { + case 0: + case D_VARPAR: + df_warning(nd, df, "never used/assigned"); + break; + case D_USED: + df_warning(nd, df, "never assigned"); + break; + case D_VALPAR: + case D_DEFINED: + case D_DEFINED | D_VALPAR: + df_warning(nd, df, "never used"); + break; } } -WalkDefList(df, proc) - register t_def *df; - int (*proc)(); +WalkDefList(df, proc) register t_def* df; +int (*proc)(); { - for (; df; df = df->df_nextinscope) { + for (; df; df = df->df_nextinscope) + { (*proc)(df); } } #ifdef DBSYMTAB static int -stabdef(df) - t_def *df; + stabdef(df) + t_def* df; { - switch(df->df_kind) { - case D_CONST: - case D_VARIABLE: - stb_string(df, df->df_kind); - break; + switch (df->df_kind) + { + case D_CONST: + case D_VARIABLE: + stb_string(df, df->df_kind); + break; } } #endif diff --git a/lang/m2/libm2/Conversion.def b/lang/m2/libm2/Conversions.def similarity index 100% rename from lang/m2/libm2/Conversion.def rename to lang/m2/libm2/Conversions.def diff --git a/lang/m2/libm2/Conversion.mod b/lang/m2/libm2/Conversions.mod similarity index 100% rename from lang/m2/libm2/Conversion.mod rename to lang/m2/libm2/Conversions.mod diff --git a/lang/m2/libm2/RealConver.def b/lang/m2/libm2/RealConversions.def similarity index 100% rename from lang/m2/libm2/RealConver.def rename to lang/m2/libm2/RealConversions.def diff --git a/lang/m2/libm2/RealConver.mod b/lang/m2/libm2/RealConversions.mod similarity index 100% rename from lang/m2/libm2/RealConver.mod rename to lang/m2/libm2/RealConversions.mod diff --git a/lang/m2/libm2/build.lua b/lang/m2/libm2/build.lua index d0861b966..a1a9e5c0a 100644 --- a/lang/m2/libm2/build.lua +++ b/lang/m2/libm2/build.lua @@ -29,8 +29,8 @@ for _, plat in ipairs(vars.plats) do }, hdrs = {}, -- must be empty deps = { - "lang/cem/libcc.ansi/headers+headers", - "plat/"..plat.."/include+headers", + "lang/cem/libcc.ansi/headers+pkg", + "plat/"..plat.."/include+pkg", "h+emheaders", }, vars = { plat = plat } diff --git a/lang/occam/comp/em.c b/lang/occam/comp/em.c index ecd779824..605817371 100644 --- a/lang/occam/comp/em.c +++ b/lang/occam/comp/em.c @@ -355,7 +355,7 @@ void zgt(lab) int lab; { C_zgt((label) lab); } void zlt(lab) int lab; { C_zlt((label) lab); } void zne(lab) int lab; { C_zne((label) lab); } -char *itoa(i) long i; +char *myitoa(i) long i; { static char a[sizeof(long)*3]; sprint(a, "%ld", i); @@ -364,7 +364,7 @@ char *itoa(i) long i; void rom(size, c) int size; long c; { - C_rom_icon(itoa(c), (arith) size); + C_rom_icon(myitoa(c), (arith) size); } void lin() diff --git a/lang/pc/comp/LLlex.c b/lang/pc/comp/LLlex.c index 7bd857a2b..4de2c0d8b 100644 --- a/lang/pc/comp/LLlex.c +++ b/lang/pc/comp/LLlex.c @@ -164,14 +164,10 @@ register int delim; Malloc((unsigned) sizeof(struct string)); register char *p; register int len = ISTRSIZE; - + str->s_str = p = Malloc((unsigned int) ISTRSIZE); for( ; ; ) { LoadChar(ch); - if( ch & 0200 ) { - fatal("non-ascii '\\%03o' read", ch & 0377); - /*NOTREACHED*/ - } if( class(ch) == STNL ) { lexerror("newline in string"); LineNumber++; @@ -310,11 +306,6 @@ again: LoadChar(ch); if( !options['C'] ) /* -C : cases are different */ TO_LOWER(ch); - - if( (ch & 0200) && ch != EOI ) { - fatal("non-ascii '\\%03o' read", ch & 0377); - /*NOTREACHED*/ - } } switch( class(ch) ) { @@ -420,7 +411,7 @@ again: /* dtrg: removed to allow Pascal programs to access system routines * (necessary to make them do anything useful). What's this for, * anyway? */ - + #if 0 if( buf[0] == '_' ) lexerror("underscore starts identifier"); #endif @@ -492,7 +483,7 @@ again: PushBack(); goto end; } - + } if( ch == 'e' || ch == 'E' ) { char *tp = np; /* save position in string */ diff --git a/lang/pc/comp/em_pc.6 b/lang/pc/comp/em_pc.6 index f544e0536..7ba0de3eb 100644 --- a/lang/pc/comp/em_pc.6 +++ b/lang/pc/comp/em_pc.6 @@ -1,4 +1,4 @@ -.TH EM_PC 6 "$Revision$" +.TH EM_PC 6 2017-01-18 .ad .SH NAME em_pc \- Pascal compiler @@ -45,9 +45,9 @@ and the \fIn\fR parameter for the alignment of that type. Absence of \fIm\fR or \fIn\fR causes a default value to be retained. .IP \fB\-w\fR suppress warning messages. -.IP .IP \fB\-R\fR -disable range checks. Additionally, the run-time tests to see if +disable range checks. +Additionally, the run-time tests to see if a function is assigned, are skipped. .IP \fB\-A\fR enable extra array bound checks, for machines that do not implement the @@ -55,26 +55,28 @@ EM ones. .IP \fB\-C\fR the lower case and upper case letters are treated differently. .IP "\fB\-u\fR, \fB\-U\fR" -allow underscores in identifiers. It is not allowed to start an identifier +allow underscores in identifiers. +It is not allowed to start an identifier with an underscore. .IP \fB\-a\fR don't generate code for assertions. .IP \fB\-c\fR -allow C-like strings. This option is mainly intended for usage with -C-functions. This option will cause the type 'string' to be known. +allow C-like strings. +This option is mainly intended for usage with C-functions. +This option will cause the type 'string' to be known. .IP \fB\-d\fR allow the type 'long'. .IP \fB\-i\fR\fIn\fR set the size of integer sets to \fIn\fR. When not used, a default value is retained. .IP \fB\-s\fR -allow only standard Pascal. This disables the \fB\-c\fR, \fB\-d\fR, \fB\-u\fR, -\fB\-U\fR and \fB\-C\fR -options. Furthermore, assertions are not recognized at all (instead of just +allow only standard Pascal. +This disables the \fB\-c\fR, \fB\-d\fR, \fB\-u\fR, +\fB\-U\fR and \fB\-C\fR options. +Furthermore, assertions are not recognized at all (instead of just being skipped). .IP \fB\-t\fR trace calls and exits of procedures and functions. -.PP .SH FILES .IR ~em/lib/em_pc : binary of the Pascal compiler. diff --git a/lang/pc/comp/type.c b/lang/pc/comp/type.c index faca8fee5..d13419cf4 100644 --- a/lang/pc/comp/type.c +++ b/lang/pc/comp/type.c @@ -94,8 +94,8 @@ InitTypes() /* character type */ char_type = standard_type(T_CHAR, 1, (arith) 1); - char_type->enm_ncst = 128; /* only 7 bits ASCII characters */ - + char_type->enm_ncst = 256; /* all bytes */ + /* boolean type */ bool_type = standard_type(T_ENUMERATION, 1, (arith) 1); diff --git a/lang/pc/libpc/build.lua b/lang/pc/libpc/build.lua index 7845991e5..215f0c745 100644 --- a/lang/pc/libpc/build.lua +++ b/lang/pc/libpc/build.lua @@ -17,8 +17,8 @@ for _, plat in ipairs(vars.plats) do }, hdrs = {}, -- must be empty deps = { - "lang/cem/libcc.ansi/headers+headers", - "plat/"..plat.."/include+headers", + "lang/cem/libcc.ansi/headers+pkg", + "plat/"..plat.."/include+pkg", "h+emheaders", }, vars = { plat = plat } diff --git a/lib/6500/descr b/lib/6500/descr index 70c5445b4..32885519b 100644 --- a/lib/6500/descr +++ b/lib/6500/descr @@ -29,19 +29,19 @@ name asld mapflag -i IFILE={EM}/{RT}i mapflag -ansi C_LIB={EM}/{LIB}ac args {IFILE?} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) \ ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ - (.mod.ocm.b.c.p.e:{TAIL}={EM}/{LIB}mon) \ + (.mod.ocm.bas.c.p.e:{TAIL}={EM}/{LIB}mon) \ (.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon2 {EM}/lib/{M}/end_em) linker end diff --git a/lib/6800/descr b/lib/6800/descr index 59bcabf56..7bf0b53c4 100644 --- a/lib/6800/descr +++ b/lib/6800/descr @@ -25,19 +25,19 @@ name led program {EM}/lib.bin/em_led mapflag -l* LNAME={EM}/{LIB}* args (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) \ ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ - (.mod.ocm.b.c.p.e:{TAIL}={EM}/{LIB}mon) \ + (.mod.ocm.bas.c.p.e:{TAIL}={EM}/{LIB}mon) \ (.e:{TAIL}={EM}/{LIB}em {EM}/lib/{M}/end_em) linker end diff --git a/lib/6805/descr b/lib/6805/descr index c4b0077a3..3081cd2d7 100644 --- a/lib/6805/descr +++ b/lib/6805/descr @@ -25,19 +25,19 @@ name led program {EM}/lib.bin/em_led mapflag -l* LNAME={EM}/{LIB}* args (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) \ ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ - (.mod.ocm.b.c.p.e:{TAIL}={EM}/{LIB}mon) \ + (.mod.ocm.bas.c.p.e:{TAIL}={EM}/{LIB}mon) \ (.e:{TAIL}={EM}/{LIB}em {EM}/lib/{M}/end_em) linker end diff --git a/lib/6809/descr b/lib/6809/descr index b42be9d4a..1d9848569 100644 --- a/lib/6809/descr +++ b/lib/6809/descr @@ -26,19 +26,19 @@ name led program {EM}/lib.bin/em_led mapflag -l* LNAME={EM}/{LIB}* args -b0:0x800 (.e:{HEAD}={ALIGN} {EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) \ ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ - (.mod.ocm.b.c.p.e:{TAIL}={EM}/{LIB}mon) \ + (.mod.ocm.bas.c.p.e:{TAIL}={EM}/{LIB}mon) \ (.e:{TAIL}={EM}/{LIB}em {EM}/lib/{M}/end_em) linker end diff --git a/lib/arm/descr b/lib/arm/descr index 4f12cc1da..cd49778a0 100644 --- a/lib/arm/descr +++ b/lib/arm/descr @@ -37,7 +37,7 @@ name asld mapflag -l* LNAME={EM}/{LIB}* mapflag -ansi C_LIB={EM}/{LIB}ac args (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.f={EM}/{RT}ac) \ @@ -45,14 +45,14 @@ name asld ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f77 {EM}/{LIB}ac) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ - (.mod.ocm.b.c.p.f.e:{TAIL}={EM}/{LIB}mon) \ - (.mod.ocm.b.c.p.f.e:{TAIL}={EM}/{LIB}fp) \ + (.mod.ocm.bas.c.p.f.e:{TAIL}={EM}/{LIB}mon) \ + (.mod.ocm.bas.c.p.f.e:{TAIL}={EM}/{LIB}fp) \ (.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon2 {EM}/lib/{M}/end_em) linker end diff --git a/lib/descr/cpm b/lib/descr/cpm index 9575b3222..e414ed68f 100644 --- a/lib/descr/cpm +++ b/lib/descr/cpm @@ -22,7 +22,7 @@ name asld mapflag -s* SIZE_F=-s* args {ASS_F?} ({RTS}:.b.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.b.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \ (.b.c.p:{TAIL}={EM}/{LIB}mon) linker diff --git a/lib/descr/fe b/lib/descr/fe index e88663a6d..b7a07cdc4 100644 --- a/lib/descr/fe +++ b/lib/descr/fe @@ -153,20 +153,20 @@ name ocm prep cond callname ocm end -name abc - from .b +name basic + from .bas to .k program {EM}/lib/ack/em_bem - mapflag -h ABC_F={ABC_F?} -h - mapflag -w ABC_F={ABC_F?} -w - mapflag -L ABC_F={ABC_F?} -L - mapflag -E ABC_F={ABC_F?} -E -# mapflag -d ABC_F={ABC_F?} -d - args -Vw{w}p{p}f{d} {ABC_F?} < > {SOURCE} + mapflag -h BASIC_F={BASIC_F?} -h + mapflag -w BASIC_F={BASIC_F?} -w + mapflag -L BASIC_F={BASIC_F?} -L + mapflag -E BASIC_F={BASIC_F?} -E +# mapflag -d BASIC_F={BASIC_F?} -d + args -Vw{w}p{p}f{d} {BASIC_F?} < > {SOURCE} prep cond - rts .b - need .b - callname abc + rts .bas + need .bas + callname basic end var A68INIT={EM}/lib/ack/em_a68s_init name a68s @@ -180,6 +180,17 @@ name a68s need .8 callname a68s end +name b + from .b + to .k + program {EM}/lib/ack/em_b + mapflag -B* ABC_F={ABC_F?} -B* + args -i < -o > -w {p} {ABC_F?} + prep cond + rts .b + need .b + callname abc +end name encode from .e to .k diff --git a/lib/em22/descr b/lib/em22/descr index ca39d5a94..551222b05 100644 --- a/lib/em22/descr +++ b/lib/em22/descr @@ -25,17 +25,17 @@ name asld mapflag -s* SIZE_FLAG=-s* mapflag -ansi C_LIB={EM}/{LIB}ac args {SIZE_FLAG} \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.mod={EM}/{RT}m2) \ ({RTS}:.p={EM}/{RT}pc) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ (.b.c.ocm.mod.p.e:{TAIL}={EM}/{LIB}mon) \ ({RTS}{ANSI?}:.cansi={EM}/lib/em22/end_em) diff --git a/lib/em24/descr b/lib/em24/descr index aa04837d7..b3eeb0fb9 100644 --- a/lib/em24/descr +++ b/lib/em24/descr @@ -25,17 +25,17 @@ name asld mapflag -s* SIZE_FLAG=-s* mapflag -ansi C_LIB={EM}/{LIB}ac args {SIZE_FLAG} \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.mod={EM}/{RT}m2) \ ({RTS}:.p={EM}/{RT}pc) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ (.p.b.mod.ocm.c.e:{TAIL}={EM}/{LIB}mon) \ ({RTS}{ANSI?}:.cansi={EM}/lib/em24/end_em) diff --git a/lib/em44/descr b/lib/em44/descr index 0b4439ced..79531e21b 100644 --- a/lib/em44/descr +++ b/lib/em44/descr @@ -25,7 +25,7 @@ name asld mapflag -s* SIZE_FLAG=-s* mapflag -ansi C_LIB={EM}/{LIB}ac args {SIZE_FLAG} \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.f={EM}/{RT}ac) \ @@ -33,11 +33,11 @@ name asld ({RTS}:.p={EM}/{RT}pc) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f77 {EM}/{LIB}ac) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ (.p.b.ocm.mod.c.f.e:{TAIL}={EM}/{LIB}mon) \ ({RTS}{ANSI?}:.cansi={EM}/lib/em44/end_em) diff --git a/lib/i286/descr b/lib/i286/descr index 31b74f2b8..9d505d3ca 100644 --- a/lib/i286/descr +++ b/lib/i286/descr @@ -28,7 +28,7 @@ name asld args {IFILE?} (.e:{HEAD}={EM}/{RT}em) \ ({RTS}:.b.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.b.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \ (.b.c.p.e:{TAIL}={EM}/{LIB}alo) (.b.c.p:{TAIL}={EM}/{LIB}mon) \ (.e:{TAIL}={EM}/{LIB}em) diff --git a/lib/i386/descr b/lib/i386/descr index a6ef6b3d8..c8a26cbf5 100644 --- a/lib/i386/descr +++ b/lib/i386/descr @@ -41,7 +41,7 @@ name led mapflag -ansi C_LIB={EM}/{LIB}ac mapflag -g LIBDB={EM}/{LIB}db args {ALIGN} {SEPID?} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.mod={EM}/{RT}m2) \ @@ -49,11 +49,11 @@ name led ({RTS}:.p={EM}/{RT}pc) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f {EM}/{LIB}ac) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {FLOATS?} \ {LIBDB?} \ diff --git a/lib/i80/descr b/lib/i80/descr index 9964d031a..293352338 100644 --- a/lib/i80/descr +++ b/lib/i80/descr @@ -36,19 +36,19 @@ name led mapflag -l* LNAME={EM}/{LIB}* mapflag -ansi C_LIB={EM}/{LIB}ac args -b0:0x1000 {ALIGN} {SEPID?} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) \ ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ - (.mod.ocm.b.c.p.e:{TAIL}={EM}/{LIB}mon) \ + (.mod.ocm.bas.c.p.e:{TAIL}={EM}/{LIB}mon) \ (.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon2 {EM}/lib/{M}/end_em) linker end diff --git a/lib/i86/descr b/lib/i86/descr index 7fcb90e0d..1d402fba5 100644 --- a/lib/i86/descr +++ b/lib/i86/descr @@ -38,17 +38,17 @@ name led mapflag -fp FLOATS={EM}/{ILIB}fp mapflag -ansi C_LIB={EM}/{LIB}ac args {ALIGN} {SEPID?} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.mod={EM}/{RT}m2) \ ({RTS}:.p={EM}/{RT}pc) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {FLOATS?} \ (.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon {EM}/lib/{M}/end_em) diff --git a/lib/m68020/descr b/lib/m68020/descr index 2e3e7fbc5..73b147869 100644 --- a/lib/m68020/descr +++ b/lib/m68020/descr @@ -49,7 +49,7 @@ name led mapflag -ansi C_LIB={EM}/{LIB}ac mapflag -g LIBDB={EM}/{LIB}db args {ALIGN} (.e:{HEAD}= {EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.f={EM}/{RT}ac) \ @@ -57,11 +57,11 @@ name led ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f77 {EM}/{LIB}ac) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBFP?} \ {LIBDB?} \ diff --git a/lib/m68k2/descr b/lib/m68k2/descr index 61dcbdb08..581debf09 100644 --- a/lib/m68k2/descr +++ b/lib/m68k2/descr @@ -51,17 +51,17 @@ name led mapflag -fp LIBFP={EM}/{LIB}fp mapflag -ansi C_LIB={EM}/{LIB}ac args -b0:0x20000 {ALIGN} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) \ ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBFP?} \ (.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon {EM}/lib/{M}/end_em) diff --git a/lib/m68k4/descr b/lib/m68k4/descr index bc2fa4992..ca628d5c6 100644 --- a/lib/m68k4/descr +++ b/lib/m68k4/descr @@ -51,7 +51,7 @@ name led mapflag -fp LIBFP={EM}/{LIB}fp mapflag -ansi C_LIB={EM}/{LIB}ac args -b0:0x20000 {ALIGN} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.f={EM}/{RT}ac) \ @@ -59,11 +59,11 @@ name led ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f77 {EM}/{LIB}ac) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBFP?} \ (.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon {EM}/lib/{M}/end_em) diff --git a/lib/mantra/descr b/lib/mantra/descr index 2183e9555..8ca806316 100644 --- a/lib/mantra/descr +++ b/lib/mantra/descr @@ -52,7 +52,7 @@ name led mapflag -fp LIBFP={EM}/{MLIB}fp mapflag -ansi C_LIB={EM}/{LIB}ac args -b0:0x80000 {ALIGN} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.mod={EM}/{RT}m2) \ @@ -60,11 +60,11 @@ name led ({RTS}:.p={EM}/{RT}pc) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f77 {EM}/{LIB}ac) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBFP?} \ (.e:{TAIL}={EM}/{MLIB}em {EM}/{LIB}mon {EM}/lib/{M}/end_em) diff --git a/lib/minix/descr b/lib/minix/descr index 45b22a525..66e48c8a9 100644 --- a/lib/minix/descr +++ b/lib/minix/descr @@ -42,14 +42,14 @@ name led mapflag -ansi C_LIB={EM}/{LIB}ac args {ALIGN} {SEPID?} \ (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBFP?} \ (.e:{TAIL}={EM}/{MLIB}em {EM}/{LIB}mon {EM}/lib/i86/end_em) diff --git a/lib/minixST/descr b/lib/minixST/descr index cd3f7b838..e9326714d 100644 --- a/lib/minixST/descr +++ b/lib/minixST/descr @@ -41,17 +41,17 @@ name led mapflag -fp LIBFP={EM}/{NLIB}fp mapflag -ansi C_LIB={EM}/{LIB}ac args {ALIGN} {SEPID?} -c (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) \ ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBFP?} \ (.e:{TAIL}={EM}/{LIB}mon {EM}/{MLIB}em {EM}/lib/m68k2/end_em) diff --git a/lib/ns/descr b/lib/ns/descr index 1fe1b8f82..7b21ddc19 100644 --- a/lib/ns/descr +++ b/lib/ns/descr @@ -36,7 +36,7 @@ name led mapflag -l* LNAME={EM}/{LIB}* mapflag -ansi C_LIB={EM}/{LIB}ac args {ALIGN} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.f={EM}/{RT}ac) \ @@ -44,11 +44,11 @@ name led ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f77 {EM}/{LIB}ac) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ (.e:{TAIL}={EM}/{LIB}mon {EM}/{LIB}mon2 {EM}/{LIB}em {EM}/lib/{M}/end_em) linker diff --git a/lib/pdp/descr b/lib/pdp/descr index 46d403b54..7b4bf0f0d 100644 --- a/lib/pdp/descr +++ b/lib/pdp/descr @@ -47,17 +47,17 @@ name led mapflag -nr ALIGN=-a0:1 -a1:1 -a2:0x2000 -a3:1 mapflag -ansi C_LIB={EM}/{LIB}ac args {ALIGN} {SEPID?} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.mod={EM}/{RT}m2) \ ({RTS}:.p={EM}/{RT}pc) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ (.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon {EM}/lib/{M}/end_em) linker diff --git a/lib/pmds/descr b/lib/pmds/descr index c5f76c60d..96342504c 100644 --- a/lib/pmds/descr +++ b/lib/pmds/descr @@ -53,17 +53,17 @@ name led mapflag -fp LIBFP={EM}/{MLIB}fp mapflag -ansi C_LIB={EM}/{LIB}ac args {ALIGN} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) \ ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBFP?} \ (.e:{TAIL}={EM}/{MLIB}em {EM}/{LIB}mon {EM}/lib/{M}/end_em) diff --git a/lib/pmds4/descr b/lib/pmds4/descr index 0802f1cc1..8ae806f24 100644 --- a/lib/pmds4/descr +++ b/lib/pmds4/descr @@ -53,7 +53,7 @@ name led mapflag -fp LIBFP={EM}/{MLIB}fp mapflag -ansi C_LIB={EM}/{LIB}ac args {ALIGN} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.f={EM}/{RT}ac) \ @@ -61,11 +61,11 @@ name led ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f77 {EM}/{LIB}ac) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBFP?} \ (.e:{TAIL}={EM}/{MLIB}em {EM}/{LIB}mon {EM}/lib/{M}/end_em) diff --git a/lib/s2650/descr b/lib/s2650/descr index 11028bd59..a9fdc0076 100644 --- a/lib/s2650/descr +++ b/lib/s2650/descr @@ -25,19 +25,19 @@ name led program {EM}/lib.bin/em_led mapflag -l* LNAME={EM}/{LIB}* args (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) \ ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ - (.mod.ocm.b.c.p.e:{TAIL}={EM}/{LIB}mon) \ + (.mod.ocm.bas.c.p.e:{TAIL}={EM}/{LIB}mon) \ (.e:{TAIL}={EM}/{LIB}em {EM}/lib/{M}/end_em) linker end diff --git a/lib/sparc/descr b/lib/sparc/descr index 10d129b47..1730f009e 100644 --- a/lib/sparc/descr +++ b/lib/sparc/descr @@ -48,7 +48,7 @@ name led mapflag -ansi C_LIB={EM}/{LIB}ac args -Bstatic -dc -e begtext \ (.e:{HEAD}= {EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.f={EM}/{RT}ac) \ @@ -59,11 +59,11 @@ name led (.8:{TAIL}={EM}/{LIB}a68s) \ (.p:{TAIL}={EM}/{LIB}pc) \ (.cp.8:{TAIL}={EM}/{LIB}cpc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f77 {EM}/{LIB}ac) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBDB?} \ (.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon {EM}/lib/{M}/end_em) diff --git a/lib/sparc_solaris/descr b/lib/sparc_solaris/descr index 43faa72ab..137768b9d 100644 --- a/lib/sparc_solaris/descr +++ b/lib/sparc_solaris/descr @@ -48,7 +48,7 @@ name led mapflag -ansi C_LIB={EM}/{LIB}ac args \ (.e:{HEAD}= {EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.f={EM}/{RT}ac) \ @@ -59,11 +59,11 @@ name led (.8:{TAIL}={EM}/{LIB}a68s) \ (.p:{TAIL}={EM}/{LIB}pc) \ (.cp.8:{TAIL}={EM}/{LIB}cpc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f77 {EM}/{LIB}ac) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBDB?} \ (.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon -lc {EM}/lib/{M}/end_em) diff --git a/lib/sun2/descr b/lib/sun2/descr index 84507ffdb..b4a20bdf0 100644 --- a/lib/sun2/descr +++ b/lib/sun2/descr @@ -55,7 +55,7 @@ name led mapflag -fp LIBFP={EM}/{MLIB}fp mapflag -ansi C_LIB={EM}/{LIB}ac args {ALIGN} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.f={EM}/{RT}ac) \ @@ -63,11 +63,11 @@ name led ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f77 {EM}/{LIB}ac) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBFP?} \ (.e:{TAIL}={EM}/{MLIB}em {EM}/{LIB}mon {EM}/lib/{M}/end_em) diff --git a/lib/sun3/descr b/lib/sun3/descr index a1d3a33d0..4cf88dd52 100644 --- a/lib/sun3/descr +++ b/lib/sun3/descr @@ -56,7 +56,7 @@ name led mapflag -g LIBDB={EM}/{MLIB}db mapflag -ansi C_LIB={EM}/{LIB}ac args {ALIGN} (.e:{HEAD}= {EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.mod={EM}/{RT}m2) \ @@ -67,11 +67,11 @@ name led (.8:{TAIL}={EM}/{LIB}a68s) \ (.p:{TAIL}={EM}/{LIB}pc) \ (.cp.8:{TAIL}={EM}/{LIB}cpc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f77 {EM}/{LIB}ac) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBFP?} \ {LIBDB?} \ diff --git a/lib/vax4/descr b/lib/vax4/descr index d17a937e4..ef2c96e58 100644 --- a/lib/vax4/descr +++ b/lib/vax4/descr @@ -51,7 +51,7 @@ name led mapflag -ansi C_LIB={EM}/{LIB}ac mapflag -g LIBDB={EM}/{LIB}db args {ALIGN} (.e:{HEAD}= {EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.mod={EM}/{RT}m2) \ @@ -60,11 +60,11 @@ name led -o > < \ (.8:{TAIL}={EM}/{LIB}a68s) \ (.p.8:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f77 {EM}/{LIB}ac) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBDB?} \ (.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon {EM}/lib/{M}/end_em) diff --git a/lib/xenix3/descr b/lib/xenix3/descr index 2d3f85d0d..9fefc2a9e 100644 --- a/lib/xenix3/descr +++ b/lib/xenix3/descr @@ -40,17 +40,17 @@ name led mapflag -fp FLOATS={EM}/{ILIB}fp mapflag -ansi C_LIB={EM}/{LIB}ac args {ALIGN} {SEPID?} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) \ ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {FLOATS?} \ (.e:{TAIL}={EM}/{ILIB}em {EM}/{LIB}mon {EM}/lib/i86/end_em) diff --git a/lib/z80/descr b/lib/z80/descr index cd1fd4850..152b5d7df 100644 --- a/lib/z80/descr +++ b/lib/z80/descr @@ -35,19 +35,19 @@ name led mapflag -l* LNAME={EM}/{LIB}* mapflag -ansi C_LIB={EM}/{LIB}ac args -b0:0x1000 (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) \ ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ - (.mod.ocm.b.c.p.e:{TAIL}={EM}/{LIB}mon) \ + (.mod.ocm.bas.c.p.e:{TAIL}={EM}/{LIB}mon) \ (.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon2 {EM}/lib/{M}/end_em) linker end diff --git a/lib/z8000/descr b/lib/z8000/descr index 61085f014..1ac1780e5 100644 --- a/lib/z8000/descr +++ b/lib/z8000/descr @@ -29,19 +29,19 @@ name asld mapflag -i IFILE={EM}/{RT}i mapflag -ansi C_LIB={EM}/{LIB}ac args {IFILE?} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) \ ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ - (.mod.ocm.b.c.p.e:{TAIL}={EM}/{LIB}mon) \ + (.mod.ocm.bas.c.p.e:{TAIL}={EM}/{LIB}mon) \ (.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon2 {EM}/lib/z8000/end_em) linker end diff --git a/mach/i386/ncg/mach.h b/mach/i386/ncg/mach.h index e58f4f423..f3075a37f 100644 --- a/mach/i386/ncg/mach.h +++ b/mach/i386/ncg/mach.h @@ -11,6 +11,7 @@ #define newilb(x) fprintf(codefile,"%s:\n",x) #define newdlb(x) fprintf(codefile,"%s:\n",x) +#define newplb(x) fprintf(codefile,".align 4\n%s:\n", x) #define dlbdlb(x,y) fprintf(codefile,"%s = %s\n",x,y) #define newlbss(l,x) fprintf(codefile,".comm %s,%ld\n",l,x); diff --git a/mach/i80/as/mach0.c b/mach/i80/as/mach0.c index 2249df643..e5a7e88ec 100644 --- a/mach/i80/as/mach0.c +++ b/mach/i80/as/mach0.c @@ -9,3 +9,5 @@ */ #define LISTING #define RELOCATION +#define THREE_PASS + diff --git a/mach/i86/ncg/mach.h b/mach/i86/ncg/mach.h index 8f9f65938..ab5a0d156 100644 --- a/mach/i86/ncg/mach.h +++ b/mach/i86/ncg/mach.h @@ -11,6 +11,7 @@ #define newilb(x) fprintf(codefile,"%s:\n",x) #define newdlb(x) fprintf(codefile,"%s:\n",x) +#define newplb(x) fprintf(codefile,".align 2\n%s:\n", x) #define dlbdlb(x,y) fprintf(codefile,"%s = %s\n",x,y) #define newlbss(l,x) fprintf(codefile,".comm %s,%u\n",l,x); diff --git a/mach/powerpc/as/mach0.c b/mach/powerpc/as/mach0.c index 325c08910..1c2051753 100644 --- a/mach/powerpc/as/mach0.c +++ b/mach/powerpc/as/mach0.c @@ -11,15 +11,13 @@ #define DEBUG 0 #undef valu_t -#define valu_t long +#define valu_t int32_t #undef ADDR_T -#define ADDR_T long +#define ADDR_T uint32_t #undef word_t -#define word_t long - -typedef uint32_t quad; +#define word_t uint32_t #undef ALIGNWORD #define ALIGNWORD 4 @@ -31,3 +29,9 @@ typedef uint32_t quad; #define VALWIDTH 8 #define FIXUPFLAGS (RELBR | RELWR) + +/* 6-bit mb (mask begin) or me (mask end) field */ +#define MB6(v) (((v) & 0x1F)<<6 | ((v) & 0x20)>>0) + +/* 6-bit sh (shift) field */ +#define SH6(v) (((v) & 0x1F)<<11 | ((v) & 0x20)>>4) diff --git a/mach/powerpc/as/mach1.c b/mach/powerpc/as/mach1.c index 998cd8d9c..50f799684 100644 --- a/mach/powerpc/as/mach1.c +++ b/mach/powerpc/as/mach1.c @@ -3,3 +3,10 @@ * $State$ */ +/* + * Do not #include anything here. Do it in mach/proto/as/comm0.h + */ + +void no_hl(void); +word_t eval_hl(struct expr_t* expr, int token); +void emit_hl(word_t in); diff --git a/mach/powerpc/as/mach2.c b/mach/powerpc/as/mach2.c index 96d6690df..4065334e6 100644 --- a/mach/powerpc/as/mach2.c +++ b/mach/powerpc/as/mach2.c @@ -8,20 +8,35 @@ %token FPR %token CR %token C +%token OP_HI OP_HA OP_LO %token OP +%token OP_BDA +%token OP_BDL %token OP_BF %token OP_BF_BFA %token OP_BF_FRA_FRB %token OP_BF_L_RA_RB %token OP_BF_L_RA_SI %token OP_BF_L_RA_UI +%token OP_BF_RA_RB +%token OP_BF_RA_SI +%token OP_BF_RA_UI %token OP_BF_U_C +%token OP_BH +%token OP_BI_BDA +%token OP_BI_BDL +%token OP_BI_BH +%token OP_BICR_BDA +%token OP_BICR_BDL +%token OP_BICR_BH %token OP_BO_BI_BDA %token OP_BO_BI_BDL %token OP_BO_BI_BH %token OP_BT_C +%token OP_BT_BA_BA %token OP_BT_BA_BB +%token OP_BT_BT_BT %token OP_FLM_FRB_C %token OP_FRS_RA_D %token OP_FRS_RA_RB @@ -32,34 +47,28 @@ %token OP_FRT_FRB_C %token OP_FRT_RA_D %token OP_FRT_RA_RB -%token OP_L %token OP_LEV %token OP_LIA %token OP_LIL -%token OP_L_RB -%token OP_RA_RB -%token OP_RB -%token OP_RS +%token OP_LI32 +%token OP_RA_RS_C +%token OP_RA_RS_RB_C +%token OP_RA_RS_RB_MB5_ME5_C +%token OP_RA_RS_RB_MB6_C +%token OP_RA_RS_SH5_C +%token OP_RA_RS_SH5_MB5_ME5_C +%token OP_RA_RS_SH6_C +%token OP_RA_RS_SH6_MB6_C +%token OP_RA_RS_UI +%token OP_RA_RS_UI_CC %token OP_RS_FXM -%token OP_RS_L %token OP_RS_RA -%token OP_RS_RA_C %token OP_RS_RA_D %token OP_RS_RA_DS %token OP_RS_RA_NB %token OP_RS_RA_RB %token OP_RS_RA_RB_C %token OP_RS_RA_RA_C -%token OP_RS_RA_RB_MB5_ME5_C -%token OP_RS_RA_RB_MB6_C -%token OP_RS_RA_RB_ME6_C -%token OP_RS_RA_SH_MB5_ME5_C -%token OP_RS_RA_SH_MB6_SH_C -%token OP_RS_RA_SH_ME6_SH_C -%token OP_RS_RA_SH5_C -%token OP_RS_RA_SH6_C -%token OP_RS_RA_UI -%token OP_RS_RA_UI_CC %token OP_RS_RB %token OP_RS_SPR %token OP_RS_SR @@ -73,19 +82,26 @@ %token OP_RT_RA_RB_C %token OP_RT_RA_SI %token OP_RT_RA_SI_addic +%token OP_RT_RA_SI_subi +%token OP_RT_RA_SI_subic %token OP_RT_RB +%token OP_RT_RB_RA_C +%token OP_RT_SI %token OP_RT_SPR %token OP_RT_SR %token OP_RT_TBR %token OP_TH_RA_RB %token OP_TO_RA_RB %token OP_TO_RA_SI - -%token OP_LA -%token OP_LI32 +%token OP_TOX_RA_RB +%token OP_TOX_RA_SI +%token OP_clrlsldi OP_clrldi OP_clrrdi OP_extldi OP_extrdi +%token OP_insrdi OP_rotrdi OP_sldi OP_srdi +%token OP_clrlslwi OP_clrlwi OP_clrrwi OP_extlwi OP_extrwi +%token OP_inslwi OP_insrwi OP_rotlwi OP_rotrwi OP_slwi OP_srwi /* Other token types */ %type c -%type e16 u8 u7 u6 u5 u4 u2 u1 -%type nb ds bda bdl lia lil +%type e16 negate16 u8 u7 u6 u5 u4 u2 u1 +%type opt_bh cr_opt nb ds bda bdl lia lil spr_num diff --git a/mach/powerpc/as/mach3.c b/mach/powerpc/as/mach3.c index 0f0bfdae7..91b088a6a 100644 --- a/mach/powerpc/as/mach3.c +++ b/mach/powerpc/as/mach3.c @@ -99,9 +99,9 @@ /* Special instructions */ 0, OP_LI32, 0, "li32", -0, OP_LA, 0, "la", -0, OP_LA, 0, "li", -0, OP_RS_RA_RA_C, 31<<26 | 444<<1, "mr", +0, OP_HI, 0, "hi16", +0, OP_HA, 0, "ha16", +0, OP_LO, 0, "lo16", /* Branch processor instructions (page 20) */ @@ -123,11 +123,173 @@ 0, OP_BT_BA_BB, 19<<26 | 193<<1, "crxor", 0, OP_BT_BA_BB, 19<<26 | 225<<1, "crnand", 0, OP_BT_BA_BB, 19<<26 | 33<<1, "crnor", -0, OP_BT_BA_BB, 19<<26 | 289<<1, "crneqv", +0, OP_BT_BA_BB, 19<<26 | 289<<1, "creqv", 0, OP_BT_BA_BB, 19<<26 | 129<<1, "crandc", 0, OP_BT_BA_BB, 19<<26 | 417<<1, "crorc", 0, OP_BF_BFA, 19<<26 | 0<<1, "mcrf", +/* extended mnemonics for bc, bcctr, bclr */ +0, OP_BH, 19<<26 | 20<<21 | 528<<1 | 0<<0, "bctr", +0, OP_BH, 19<<26 | 20<<21 | 528<<1 | 1<<0, "bctrl", +0, OP_BDL, 16<<26 | 16<<21 | 0<<1 | 0<<0, "bdnz", +0, OP_BDA, 16<<26 | 16<<21 | 1<<1 | 0<<0, "bdnza", +0, OP_BH, 19<<26 | 16<<21 | 16<<1 | 0<<0, "bdnzlr", +0, OP_BDL, 16<<26 | 16<<21 | 0<<1 | 1<<0, "bdnzl", +0, OP_BDA, 16<<26 | 16<<21 | 1<<1 | 1<<0, "bdnzla", +0, OP_BH, 19<<26 | 16<<21 | 16<<1 | 1<<0, "bdnzlrl", +0, OP_BI_BDL, 16<<26 | 0<<21 | 0<<1 | 0<<0, "bdnzf", +0, OP_BI_BDA, 16<<26 | 0<<21 | 1<<1 | 0<<0, "bdnzfa", +0, OP_BI_BH, 19<<26 | 0<<21 | 16<<1 | 0<<0, "bdnzflr", +0, OP_BI_BDL, 16<<26 | 0<<21 | 0<<1 | 1<<0, "bdnzfl", +0, OP_BI_BDA, 16<<26 | 0<<21 | 1<<1 | 1<<0, "bdnzfla", +0, OP_BI_BH, 19<<26 | 0<<21 | 16<<1 | 1<<0, "bdnzflrl", +0, OP_BI_BDL, 16<<26 | 8<<21 | 0<<1 | 0<<0, "bdnzt", +0, OP_BI_BDA, 16<<26 | 8<<21 | 1<<1 | 0<<0, "bdnzta", +0, OP_BI_BH, 19<<26 | 8<<21 | 16<<1 | 0<<0, "bdnztlr", +0, OP_BI_BDL, 16<<26 | 8<<21 | 0<<1 | 1<<0, "bdnztl", +0, OP_BI_BDA, 16<<26 | 8<<21 | 1<<1 | 1<<0, "bdnztla", +0, OP_BI_BH, 19<<26 | 8<<21 | 16<<1 | 1<<0, "bdnztlrl", +0, OP_BDL, 16<<26 | 18<<21 | 0<<1 | 0<<0, "bdz", +0, OP_BDA, 16<<26 | 18<<21 | 1<<1 | 0<<0, "bdza", +0, OP_BH, 19<<26 | 18<<21 | 16<<1 | 0<<0, "bdzlr", +0, OP_BDL, 16<<26 | 18<<21 | 0<<1 | 1<<0, "bdzl", +0, OP_BDA, 16<<26 | 18<<21 | 1<<1 | 1<<0, "bdzla", +0, OP_BH, 19<<26 | 18<<21 | 16<<1 | 1<<0, "bdzlrl", +0, OP_BI_BDL, 16<<26 | 2<<21 | 0<<1 | 0<<0, "bdzf", +0, OP_BI_BDA, 16<<26 | 2<<21 | 1<<1 | 0<<0, "bdzfa", +0, OP_BI_BH, 19<<26 | 2<<21 | 16<<1 | 0<<0, "bdzflr", +0, OP_BI_BDL, 16<<26 | 2<<21 | 0<<1 | 1<<0, "bdzfl", +0, OP_BI_BDA, 16<<26 | 2<<21 | 1<<1 | 1<<0, "bdzfla", +0, OP_BI_BH, 19<<26 | 2<<21 | 16<<1 | 1<<0, "bdzflrl", +0, OP_BI_BDL, 16<<26 | 10<<21 | 0<<1 | 0<<0, "bdzt", +0, OP_BI_BDA, 16<<26 | 10<<21 | 1<<1 | 0<<0, "bdzta", +0, OP_BI_BH, 19<<26 | 10<<21 | 16<<1 | 0<<0, "bdztlr", +0, OP_BI_BDL, 16<<26 | 10<<21 | 0<<1 | 1<<0, "bdztl", +0, OP_BI_BDA, 16<<26 | 10<<21 | 1<<1 | 1<<0, "bdztla", +0, OP_BI_BH, 19<<26 | 10<<21 | 16<<1 | 1<<0, "bdztlrl", +0, OP_BI_BDL, 16<<26 | 4<<21 | 0<<1 | 0<<0, "bf", +0, OP_BI_BDA, 16<<26 | 4<<21 | 1<<1 | 0<<0, "bfa", +0, OP_BI_BH, 19<<26 | 4<<21 | 528<<1 | 0<<0, "bfctr", +0, OP_BI_BH, 19<<26 | 4<<21 | 528<<1 | 1<<0, "bfctrl", +0, OP_BI_BDL, 16<<26 | 4<<21 | 0<<1 | 1<<0, "bfl", +0, OP_BI_BDA, 16<<26 | 4<<21 | 0<<1 | 1<<0, "bfla", +0, OP_BI_BH, 19<<26 | 4<<21 | 16<<1 | 0<<0, "bflr", +0, OP_BI_BH, 19<<26 | 4<<21 | 16<<1 | 1<<0, "bflrl", +0, OP_BH, 19<<26 | 20<<21 | 16<<1 | 0<<0, "blr", +0, OP_BH, 19<<26 | 20<<21 | 16<<1 | 1<<0, "blrl", +0, OP_BI_BDL, 16<<26 | 12<<21 | 0<<1 | 0<<0, "bt", +0, OP_BI_BDA, 16<<26 | 12<<21 | 1<<1 | 0<<0, "bta", +0, OP_BI_BH, 19<<26 | 12<<21 | 528<<1 | 0<<0, "btctr", +0, OP_BI_BH, 19<<26 | 12<<21 | 528<<1 | 1<<0, "btctrl", +0, OP_BI_BDL, 16<<26 | 12<<21 | 0<<1 | 1<<0, "btl", +0, OP_BI_BDA, 16<<26 | 12<<21 | 0<<1 | 1<<0, "btla", +0, OP_BI_BH, 19<<26 | 12<<21 | 16<<1 | 0<<0, "btlr", +0, OP_BI_BH, 19<<26 | 12<<21 | 16<<1 | 1<<0, "btlrl", + +/* extended m with condition in BI */ +0, OP_BICR_BDL, 16<<26 | 12<<21 | 2<<16 | 0<<1 | 0<<0, "beq", +0, OP_BICR_BDA, 16<<26 | 12<<21 | 2<<16 | 1<<1 | 0<<0, "beqa", +0, OP_BICR_BH, 19<<26 | 12<<21 | 2<<16 | 528<<1 | 0<<0, "beqctr", +0, OP_BICR_BH, 19<<26 | 12<<21 | 2<<16 | 528<<1 | 1<<0, "beqctrl", +0, OP_BICR_BDL, 16<<26 | 12<<21 | 2<<16 | 0<<1 | 1<<0, "beql", +0, OP_BICR_BDA, 16<<26 | 12<<21 | 2<<16 | 1<<1 | 1<<0, "beqla", +0, OP_BICR_BH, 19<<26 | 12<<21 | 2<<16 | 16<<1 | 0<<0, "beqlr", +0, OP_BICR_BH, 19<<26 | 12<<21 | 2<<16 | 16<<1 | 1<<0, "beqlrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 0<<16 | 0<<1 | 0<<0, "bge", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 0<<16 | 1<<1 | 0<<0, "bgea", +0, OP_BICR_BH, 19<<26 | 4<<21 | 0<<16 | 528<<1 | 0<<0, "bgectr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 0<<16 | 528<<1 | 1<<0, "bgectrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 0<<16 | 0<<1 | 1<<0, "bgel", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 0<<16 | 1<<1 | 1<<0, "bgela", +0, OP_BICR_BH, 19<<26 | 4<<21 | 0<<16 | 16<<1 | 0<<0, "bgelr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 0<<16 | 16<<1 | 1<<0, "bgelrl", +0, OP_BICR_BDL, 16<<26 | 12<<21 | 1<<16 | 0<<1 | 0<<0, "bgt", +0, OP_BICR_BDA, 16<<26 | 12<<21 | 1<<16 | 1<<1 | 0<<0, "bgta", +0, OP_BICR_BH, 19<<26 | 12<<21 | 1<<16 | 528<<1 | 0<<0, "bgtctr", +0, OP_BICR_BH, 19<<26 | 12<<21 | 1<<16 | 528<<1 | 1<<0, "bgtctrl", +0, OP_BICR_BDL, 16<<26 | 12<<21 | 1<<16 | 0<<1 | 1<<0, "bgtl", +0, OP_BICR_BDA, 16<<26 | 12<<21 | 1<<16 | 1<<1 | 1<<0, "bgtla", +0, OP_BICR_BH, 19<<26 | 12<<21 | 1<<16 | 16<<1 | 0<<0, "bgtlr", +0, OP_BICR_BH, 19<<26 | 12<<21 | 1<<16 | 16<<1 | 1<<0, "bgtlrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 1<<16 | 0<<1 | 0<<0, "ble", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 1<<16 | 1<<1 | 0<<0, "blea", +0, OP_BICR_BH, 19<<26 | 4<<21 | 1<<16 | 528<<1 | 0<<0, "blectr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 1<<16 | 528<<1 | 1<<0, "blectrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 1<<16 | 0<<1 | 1<<0, "blel", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 1<<16 | 1<<1 | 1<<0, "blela", +0, OP_BICR_BH, 19<<26 | 4<<21 | 1<<16 | 16<<1 | 0<<0, "blelr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 1<<16 | 16<<1 | 1<<0, "blelrl", +0, OP_BICR_BDL, 16<<26 | 12<<21 | 0<<16 | 0<<1 | 0<<0, "blt", +0, OP_BICR_BDA, 16<<26 | 12<<21 | 0<<16 | 1<<1 | 0<<0, "blta", +0, OP_BICR_BH, 19<<26 | 12<<21 | 0<<16 | 528<<1 | 0<<0, "bltctr", +0, OP_BICR_BH, 19<<26 | 12<<21 | 0<<16 | 528<<1 | 1<<0, "bltctrl", +0, OP_BICR_BDL, 16<<26 | 12<<21 | 0<<16 | 0<<1 | 1<<0, "bltl", +0, OP_BICR_BDA, 16<<26 | 12<<21 | 0<<16 | 1<<1 | 1<<0, "bltla", +0, OP_BICR_BH, 19<<26 | 12<<21 | 0<<16 | 16<<1 | 0<<0, "bltlr", +0, OP_BICR_BH, 19<<26 | 12<<21 | 0<<16 | 16<<1 | 1<<0, "bltlrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 2<<16 | 0<<1 | 0<<0, "bne", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 2<<16 | 1<<1 | 0<<0, "bnea", +0, OP_BICR_BH, 19<<26 | 4<<21 | 2<<16 | 528<<1 | 0<<0, "bnectr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 2<<16 | 528<<1 | 1<<0, "bnectrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 2<<16 | 0<<1 | 1<<0, "bnel", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 2<<16 | 1<<1 | 1<<0, "bnela", +0, OP_BICR_BH, 19<<26 | 4<<21 | 2<<16 | 16<<1 | 0<<0, "bnelr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 2<<16 | 16<<1 | 1<<0, "bnelrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 1<<16 | 0<<1 | 0<<0, "bng", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 1<<16 | 1<<1 | 0<<0, "bnga", +0, OP_BICR_BH, 19<<26 | 4<<21 | 1<<16 | 528<<1 | 0<<0, "bngctr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 1<<16 | 528<<1 | 1<<0, "bngctrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 1<<16 | 0<<1 | 1<<0, "bngl", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 1<<16 | 1<<1 | 1<<0, "bngla", +0, OP_BICR_BH, 19<<26 | 4<<21 | 1<<16 | 16<<1 | 0<<0, "bnglr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 1<<16 | 16<<1 | 1<<0, "bnglrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 0<<16 | 0<<1 | 0<<0, "bnl", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 0<<16 | 1<<1 | 0<<0, "bnla", +0, OP_BICR_BH, 19<<26 | 4<<21 | 0<<16 | 528<<1 | 0<<0, "bnlctr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 0<<16 | 528<<1 | 1<<0, "bnlctrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 0<<16 | 0<<1 | 1<<0, "bnll", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 0<<16 | 1<<1 | 1<<0, "bnlla", +0, OP_BICR_BH, 19<<26 | 4<<21 | 0<<16 | 16<<1 | 0<<0, "bnllr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 0<<16 | 16<<1 | 1<<0, "bnllrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 3<<16 | 0<<1 | 0<<0, "bns", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 3<<16 | 1<<1 | 0<<0, "bnsa", +0, OP_BICR_BH, 19<<26 | 4<<21 | 3<<16 | 528<<1 | 0<<0, "bnsctr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 3<<16 | 528<<1 | 1<<0, "bnsctrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 3<<16 | 0<<1 | 1<<0, "bnsl", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 3<<16 | 1<<1 | 1<<0, "bnsla", +0, OP_BICR_BH, 19<<26 | 4<<21 | 3<<16 | 16<<1 | 0<<0, "bnslr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 3<<16 | 16<<1 | 1<<0, "bnslrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 3<<16 | 0<<1 | 0<<0, "bnu", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 3<<16 | 1<<1 | 0<<0, "bnua", +0, OP_BICR_BH, 19<<26 | 4<<21 | 3<<16 | 528<<1 | 0<<0, "bnuctr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 3<<16 | 528<<1 | 1<<0, "bnuctrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 3<<16 | 0<<1 | 1<<0, "bnul", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 3<<16 | 1<<1 | 1<<0, "bnula", +0, OP_BICR_BH, 19<<26 | 4<<21 | 3<<16 | 16<<1 | 0<<0, "bnulr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 3<<16 | 16<<1 | 1<<0, "bnulrl", +0, OP_BICR_BDL, 16<<26 | 12<<21 | 3<<16 | 0<<1 | 0<<0, "bso", +0, OP_BICR_BDA, 16<<26 | 12<<21 | 3<<16 | 1<<1 | 0<<0, "bsoa", +0, OP_BICR_BH, 19<<26 | 12<<21 | 3<<16 | 528<<1 | 0<<0, "bsoctr", +0, OP_BICR_BH, 19<<26 | 12<<21 | 3<<16 | 528<<1 | 1<<0, "bsoctrl", +0, OP_BICR_BDL, 16<<26 | 12<<21 | 3<<16 | 0<<1 | 1<<0, "bsol", +0, OP_BICR_BDA, 16<<26 | 12<<21 | 3<<16 | 1<<1 | 1<<0, "bsola", +0, OP_BICR_BH, 19<<26 | 12<<21 | 3<<16 | 16<<1 | 0<<0, "bsolr", +0, OP_BICR_BH, 19<<26 | 12<<21 | 3<<16 | 16<<1 | 1<<0, "bsolrl", +0, OP_BICR_BDL, 16<<26 | 12<<21 | 3<<16 | 0<<1 | 0<<0, "bun", +0, OP_BICR_BDA, 16<<26 | 12<<21 | 3<<16 | 1<<1 | 0<<0, "buna", +0, OP_BICR_BH, 19<<26 | 12<<21 | 3<<16 | 528<<1 | 0<<0, "bunctr", +0, OP_BICR_BH, 19<<26 | 12<<21 | 3<<16 | 528<<1 | 1<<0, "bunctrl", +0, OP_BICR_BDL, 16<<26 | 12<<21 | 3<<16 | 0<<1 | 1<<0, "bunl", +0, OP_BICR_BDA, 16<<26 | 12<<21 | 3<<16 | 1<<1 | 1<<0, "bunla", +0, OP_BICR_BH, 19<<26 | 12<<21 | 3<<16 | 16<<1 | 0<<0, "bunlr", +0, OP_BICR_BH, 19<<26 | 12<<21 | 3<<16 | 16<<1 | 1<<0, "bunlrl", + +/* extended m for cr logic */ +0, OP_BT_BT_BT, 19<<26 | 289<<1, "crset", +0, OP_BT_BT_BT, 19<<26 | 193<<1, "crclr", +0, OP_BT_BA_BA, 19<<26 | 449<<1, "crmove", +0, OP_BT_BA_BA, 19<<26 | 33<<1, "crnot", + /* Fixed point instructions (page 29) */ 0, OP_RT_RA_D, 34<<26, "lbz", @@ -196,6 +358,10 @@ 0, OP_RT_RA_RB_C, 31<<26 | 1<<10 | 40<<1, "subfo", 0, OP_RT_RA_SI_addic, 12<<26, "addic", /* special case C */ 0, OP_RT_RA_SI, 8<<26, "subfic", +0, OP_RT_RA_RB_C, 31<<26 | 0<<10 | 10<<1, "addc", +0, OP_RT_RA_RB_C, 31<<26 | 1<<10 | 10<<1, "addco", +0, OP_RT_RA_RB_C, 31<<26 | 0<<10 | 8<<1, "subfc", +0, OP_RT_RA_RB_C, 31<<26 | 1<<10 | 8<<1, "subfco", 0, OP_RT_RA_RB_C, 31<<26 | 0<<10 | 138<<1, "adde", 0, OP_RT_RA_RB_C, 31<<26 | 1<<10 | 138<<1, "addeo", 0, OP_RT_RA_RB_C, 31<<26 | 0<<10 | 136<<1, "subfe", @@ -211,6 +377,20 @@ 0, OP_RT_RA_C, 31<<26 | 0<<10 | 104<<1, "neg", 0, OP_RT_RA_C, 31<<26 | 1<<10 | 104<<1, "nego", +/* extended m for addition */ +0, OP_RT_RA_D, 14<<26, "la", +0, OP_RT_SI, 14<<26 | 0<<16, "li", +0, OP_RT_SI, 15<<26 | 0<<16, "lis", + +/* extended m for subtraction */ +0, OP_RT_RB_RA_C, 31<<26 | 0<<10 | 40<<1, "sub", +0, OP_RT_RB_RA_C, 31<<26 | 1<<10 | 40<<1, "subo", +0, OP_RT_RB_RA_C, 31<<26 | 0<<10 | 8<<1, "subc", +0, OP_RT_RB_RA_C, 31<<26 | 0<<10 | 8<<1, "subco", +0, OP_RT_RA_SI_subi, 14<<26, "subi", +0, OP_RT_RA_SI_subi, 15<<26, "subis", +0, OP_RT_RA_SI_subic, 12<<26, "subic", + /* page 54 */ 0, OP_RT_RA_SI, 7<<26, "mulli", 0, OP_RT_RA_RB_C, 31<<26 | 0<<10 | 233<<1, "mulld", @@ -238,53 +418,159 @@ 0, OP_BF_L_RA_UI, 10<<26, "cmpli", 0, OP_BF_L_RA_RB, 31<<26 | 32<<1, "cmpl", +/* extended m for comparison */ +0, OP_BF_RA_SI, 11<<26 | 1<<21, "cmpdi", +0, OP_BF_RA_RB, 31<<26 | 1<<21 | 0<<1, "cmpd", +0, OP_BF_RA_UI, 10<<26 | 1<<21, "cmpldi", +0, OP_BF_RA_RB, 31<<26 | 1<<21 | 32<<1, "cmpld", +0, OP_BF_RA_SI, 11<<26 | 0<<21, "cmpwi", +0, OP_BF_RA_RB, 31<<26 | 0<<21 | 0<<1, "cmpw", +0, OP_BF_RA_UI, 10<<26 | 0<<21, "cmplwi", +0, OP_BF_RA_RB, 31<<26 | 0<<21 | 32<<1, "cmplw", + /* page 60 */ 0, OP_TO_RA_SI, 2<<26, "tdi", 0, OP_TO_RA_SI, 3<<26, "twi", 0, OP_TO_RA_RB, 31<<26 | 68<<1, "td", 0, OP_TO_RA_RB, 31<<26 | 4<<1, "tw", +/* extended m for traps */ +0, OP_TOX_RA_RB, 31<<26 | 4<<21 | 68<<1, "tdeq", +0, OP_TOX_RA_SI, 2<<26 | 4<<21, "tdeqi", +0, OP_TOX_RA_RB, 31<<26 | 12<<21 | 68<<1, "tdge", +0, OP_TOX_RA_SI, 2<<26 | 12<<21, "tdgei", +0, OP_TOX_RA_RB, 31<<26 | 8<<21 | 68<<1, "tdgt", +0, OP_TOX_RA_SI, 2<<26 | 8<<21, "tdgti", +0, OP_TOX_RA_RB, 31<<26 | 20<<21 | 68<<1, "tdle", +0, OP_TOX_RA_SI, 2<<26 | 20<<21, "tdlei", +0, OP_TOX_RA_RB, 31<<26 | 5<<21 | 68<<1, "tdlge", +0, OP_TOX_RA_SI, 2<<26 | 5<<21, "tdlgei", +0, OP_TOX_RA_RB, 31<<26 | 1<<21 | 68<<1, "tdlgt", +0, OP_TOX_RA_SI, 2<<26 | 1<<21, "tdlgti", +0, OP_TOX_RA_RB, 31<<26 | 6<<21 | 68<<1, "tdlle", +0, OP_TOX_RA_SI, 2<<26 | 6<<21, "tdllei", +0, OP_TOX_RA_RB, 31<<26 | 2<<21 | 68<<1, "tdllt", +0, OP_TOX_RA_SI, 2<<26 | 2<<21, "tdllti", +0, OP_TOX_RA_RB, 31<<26 | 6<<21 | 68<<1, "tdlng", +0, OP_TOX_RA_SI, 2<<26 | 6<<21, "tdlngi", +0, OP_TOX_RA_RB, 31<<26 | 5<<21 | 68<<1, "tdlnl", +0, OP_TOX_RA_SI, 2<<26 | 5<<21, "tdlnli", +0, OP_TOX_RA_RB, 31<<26 | 16<<21 | 68<<1, "tdlt", +0, OP_TOX_RA_SI, 2<<26 | 16<<21, "tdlti", +0, OP_TOX_RA_RB, 31<<26 | 24<<21 | 68<<1, "tdne", +0, OP_TOX_RA_SI, 2<<26 | 24<<21, "tdnei", +0, OP_TOX_RA_RB, 31<<26 | 20<<21 | 68<<1, "tdng", +0, OP_TOX_RA_SI, 2<<26 | 20<<21, "tdngi", +0, OP_TOX_RA_RB, 31<<26 | 12<<21 | 68<<1, "tdnl", +0, OP_TOX_RA_SI, 2<<26 | 12<<21, "tdnli", +0, OP_TOX_RA_RB, 31<<26 | 31<<21 | 68<<1, "tdu", +0, OP_TOX_RA_SI, 2<<26 | 31<<21, "tdui", +0, OP, 31<<26 | 31<<21 | 4<<1, "trap", +0, OP_TOX_RA_RB, 31<<26 | 4<<21 | 4<<1, "tweq", +0, OP_TOX_RA_SI, 3<<26 | 4<<21, "tweqi", +0, OP_TOX_RA_RB, 31<<26 | 12<<21 | 4<<1, "twge", +0, OP_TOX_RA_SI, 3<<26 | 12<<21, "twgei", +0, OP_TOX_RA_RB, 31<<26 | 8<<21 | 4<<1, "twgt", +0, OP_TOX_RA_SI, 3<<26 | 8<<21, "twgti", +0, OP_TOX_RA_RB, 31<<26 | 20<<21 | 4<<1, "twle", +0, OP_TOX_RA_SI, 3<<26 | 20<<21, "twlei", +0, OP_TOX_RA_RB, 31<<26 | 5<<21 | 4<<1, "twlge", +0, OP_TOX_RA_SI, 3<<26 | 5<<21, "twlgei", +0, OP_TOX_RA_RB, 31<<26 | 1<<21 | 4<<1, "twlgt", +0, OP_TOX_RA_SI, 3<<26 | 1<<21, "twlgti", +0, OP_TOX_RA_RB, 31<<26 | 6<<21 | 4<<1, "twlle", +0, OP_TOX_RA_SI, 3<<26 | 6<<21, "twllei", +0, OP_TOX_RA_RB, 31<<26 | 2<<21 | 4<<1, "twllt", +0, OP_TOX_RA_SI, 3<<26 | 2<<21, "twllti", +0, OP_TOX_RA_RB, 31<<26 | 6<<21 | 4<<1, "twlng", +0, OP_TOX_RA_SI, 3<<26 | 6<<21, "twlngi", +0, OP_TOX_RA_RB, 31<<26 | 5<<21 | 4<<1, "twlnl", +0, OP_TOX_RA_SI, 3<<26 | 5<<21, "twlnli", +0, OP_TOX_RA_RB, 31<<26 | 16<<21 | 4<<1, "twlt", +0, OP_TOX_RA_SI, 3<<26 | 16<<21, "twlti", +0, OP_TOX_RA_RB, 31<<26 | 24<<21 | 4<<1, "twne", +0, OP_TOX_RA_SI, 3<<26 | 24<<21, "twnei", +0, OP_TOX_RA_RB, 31<<26 | 20<<21 | 4<<1, "twng", +0, OP_TOX_RA_SI, 3<<26 | 20<<21, "twngi", +0, OP_TOX_RA_RB, 31<<26 | 12<<21 | 4<<1, "twnl", +0, OP_TOX_RA_SI, 3<<26 | 12<<21, "twnli", +0, OP_TOX_RA_RB, 31<<26 | 31<<21 | 4<<1, "twu", +0, OP_TOX_RA_SI, 3<<26 | 31<<21, "twui", + /* page 62 */ -0, OP_RS_RA_UI_CC, 28<<26, "andi", /* C compulsory */ -0, OP_RS_RA_UI_CC, 29<<26, "andis", /* C compulsory */ -0, OP_RS_RA_UI, 24<<26, "ori", -0, OP_RS_RA_UI, 25<<26, "oris", -0, OP_RS_RA_UI, 26<<26, "xori", -0, OP_RS_RA_UI, 27<<26, "xoris", -0, OP_RS_RA_RB_C, 31<<26 | 28<<1, "and", -0, OP_RS_RA_RB_C, 31<<26 | 444<<1, "or", -0, OP_RS_RA_RB_C, 31<<26 | 316<<1, "xor", -0, OP_RS_RA_RB_C, 31<<26 | 476<<1, "nand", -0, OP_RS_RA_RB_C, 31<<26 | 124<<1, "nor", -0, OP_RS_RA_RB_C, 31<<26 | 284<<1, "eqv", -0, OP_RS_RA_RB_C, 31<<26 | 60<<1, "andc", -0, OP_RS_RA_RB_C, 31<<26 | 412<<1, "orc", -0, OP_RS_RA_C, 31<<26 | 954<<1, "extsb", -0, OP_RS_RA_C, 31<<26 | 922<<1, "extsh", -0, OP_RS_RA_C, 31<<26 | 986<<1, "extsw", -0, OP_RS_RA_C, 31<<26 | 58<<1, "cntlzd", -0, OP_RS_RA_C, 31<<26 | 26<<1, "cntlzw", +0, OP_RA_RS_UI_CC, 28<<26, "andi", /* C compulsory */ +0, OP_RA_RS_UI_CC, 29<<26, "andis", /* C compulsory */ +0, OP_RA_RS_UI, 24<<26, "ori", +0, OP_RA_RS_UI, 25<<26, "oris", +0, OP_RA_RS_UI, 26<<26, "xori", +0, OP_RA_RS_UI, 27<<26, "xoris", +0, OP_RA_RS_RB_C, 31<<26 | 28<<1, "and", +0, OP_RA_RS_RB_C, 31<<26 | 444<<1, "or", +0, OP_RA_RS_RB_C, 31<<26 | 316<<1, "xor", +0, OP_RA_RS_RB_C, 31<<26 | 476<<1, "nand", +0, OP_RA_RS_RB_C, 31<<26 | 124<<1, "nor", +0, OP_RA_RS_RB_C, 31<<26 | 284<<1, "eqv", +0, OP_RA_RS_RB_C, 31<<26 | 60<<1, "andc", +0, OP_RA_RS_RB_C, 31<<26 | 412<<1, "orc", +0, OP_RA_RS_C, 31<<26 | 954<<1, "extsb", +0, OP_RA_RS_C, 31<<26 | 922<<1, "extsh", +0, OP_RA_RS_C, 31<<26 | 986<<1, "extsw", +0, OP_RA_RS_C, 31<<26 | 58<<1, "cntlzd", +0, OP_RA_RS_C, 31<<26 | 26<<1, "cntlzw", + +/* extended m using logic */ +0, OP_RS_RA_RA_C, 31<<26 | 444<<1, "mr", +0, OP, 24<<26, "nop", +0, OP_RS_RA_RA_C, 31<<26 | 124<<1, "not", +0, OP, 26<<26, "xnop", /* page 69 */ -0, OP_RS_RA_SH_MB6_SH_C, 30<<26 | 0<<2, "rldicl", -0, OP_RS_RA_SH_ME6_SH_C, 30<<26 | 1<<2, "rldicr", -0, OP_RS_RA_SH_MB6_SH_C, 30<<26 | 2<<2, "rldic", -0, OP_RS_RA_SH_MB5_ME5_C, 21<<26, "rlwinm", -0, OP_RS_RA_RB_MB6_C, 30<<26 | 8<<1, "rldcl", -0, OP_RS_RA_RB_ME6_C, 30<<26 | 9<<1, "rldcr", -0, OP_RS_RA_RB_MB5_ME5_C, 23<<26, "rlwnm", -0, OP_RS_RA_SH_MB6_SH_C, 30<<26 | 3<<2, "rldimi", -0, OP_RS_RA_SH_MB5_ME5_C, 20<<26, "rlwimi", +0, OP_RA_RS_SH6_MB6_C, 30<<26 | 0<<2, "rldicl", +0, OP_RA_RS_SH6_MB6_C, 30<<26 | 1<<2, "rldicr", +0, OP_RA_RS_SH6_MB6_C, 30<<26 | 2<<2, "rldic", +0, OP_RA_RS_SH5_MB5_ME5_C, 21<<26, "rlwinm", +0, OP_RA_RS_RB_MB6_C, 30<<26 | 8<<1, "rldcl", +0, OP_RA_RS_RB_MB6_C, 30<<26 | 9<<1, "rldcr", +0, OP_RA_RS_RB_MB5_ME5_C, 23<<26, "rlwnm", +0, OP_RA_RS_SH6_MB6_C, 30<<26 | 3<<2, "rldimi", +0, OP_RA_RS_SH5_MB5_ME5_C, 20<<26, "rlwimi", + +/* extended m for doubleword rotation */ +0, OP_clrlsldi, 30<<26 | 2<<2, "clrlsldi", +0, OP_clrldi, 30<<26 | 0<<2, "clrldi", +0, OP_clrrdi, 30<<26 | 1<<2, "clrrdi", +0, OP_extldi, 30<<26 | 0<<2, "extldi", +0, OP_extrdi, 30<<26 | 1<<2, "extrdi", +0, OP_insrdi, 30<<26 | 3<<2, "insrdi", +0, OP_RA_RS_RB_C, 30<<26 | MB6(0) | 8<<1, "rotld", +0, OP_RA_RS_SH6_C, 30<<26 | MB6(0) | 0<<2, "rotldi", +0, OP_rotrdi, 30<<26 | 0<<2, "rotrdi", +0, OP_sldi, 30<<26 | 1<<2, "sldi", +0, OP_srdi, 30<<26 | 0<<2, "srdi", + +/* extended m for word rotation */ +0, OP_clrlslwi, 21<<26, "clrlslwi", +0, OP_clrlwi, 21<<26, "clrlwi", +0, OP_clrrwi, 21<<26, "clrrwi", +0, OP_extlwi, 21<<26, "extlwi", +0, OP_extrwi, 21<<26, "extrwi", +0, OP_inslwi, 20<<26, "inslwi", +0, OP_insrwi, 20<<26, "insrwi", +0, OP_RA_RS_RB_C, 23<<26 | 0<<6 | 31<<1, "rotlw", +0, OP_RA_RS_SH5_C, 21<<26 | 0<<6 | 31<<1, "rotlwi", +0, OP_rotrwi, 21<<26, "rotrwi", +0, OP_slwi, 21<<26, "slwi", +0, OP_srwi, 21<<26, "srwi", /* page 74 */ -0, OP_RS_RA_RB_C, 31<<26 | 27<<1, "sld", -0, OP_RS_RA_RB_C, 31<<26 | 24<<1, "slw", -0, OP_RS_RA_RB_C, 31<<26 | 539<<1, "srd", -0, OP_RS_RA_RB_C, 31<<26 | 536<<1, "srw", -0, OP_RS_RA_SH6_C, 31<<26 | 413<<2, "sradi", -0, OP_RS_RA_SH5_C, 31<<26 | 824<<1, "srawi", -0, OP_RS_RA_RB_C, 31<<26 | 794<<1, "srad", -0, OP_RS_RA_RB_C, 31<<26 | 792<<1, "sraw", +0, OP_RA_RS_RB_C, 31<<26 | 27<<1, "sld", +0, OP_RA_RS_RB_C, 31<<26 | 24<<1, "slw", +0, OP_RA_RS_RB_C, 31<<26 | 539<<1, "srd", +0, OP_RA_RS_RB_C, 31<<26 | 536<<1, "srw", +0, OP_RA_RS_SH6_C, 31<<26 | 413<<2, "sradi", +0, OP_RA_RS_SH5_C, 31<<26 | 824<<1, "srawi", +0, OP_RA_RS_RB_C, 31<<26 | 794<<1, "srad", +0, OP_RA_RS_RB_C, 31<<26 | 792<<1, "sraw", /* page 78 */ 0, OP_RS_SPR, 31<<26 | 467<<1, "mtspr", @@ -292,6 +578,14 @@ 0, OP_RS_FXM, 31<<26 | 0<<21 | 144<<1, "mtcrf", 0, OP_RT, 31<<26 | 0<<21 | 19<<1, "mfcr", +/* extended m for special purpose registers */ +0, OP_RT, 31<<26 | 9<<16 | 0<<11 | 339<<1, "mfctr", +0, OP_RT, 31<<26 | 8<<16 | 0<<11 | 339<<1, "mflr", +0, OP_RT, 31<<26 | 1<<16 | 0<<11 | 339<<1, "mfxer", +0, OP_RT, 31<<26 | 9<<16 | 0<<11 | 467<<1, "mtctr", +0, OP_RT, 31<<26 | 8<<16 | 0<<11 | 467<<1, "mtlr", +0, OP_RT, 31<<26 | 1<<16 | 0<<11 | 467<<1, "mtxer", + /* Floating point instructions (page 83) */ 0, OP_FRT_RA_D, 48<<26, "lfs", diff --git a/mach/powerpc/as/mach4.c b/mach/powerpc/as/mach4.c index 3f79ca86c..8a0cca9de 100644 --- a/mach/powerpc/as/mach4.c +++ b/mach/powerpc/as/mach4.c @@ -4,69 +4,212 @@ */ operation - : OP_BF_BFA CR ',' CR { emit4($1 | ($2<<23) | ($4<<18)); } + : OP { emit4($1); } + | OP_BDA bda { emit4($1 | $2); } + | OP_BDL bdl { emit4($1 | $2); } + | OP_BF_BFA CR ',' CR { emit4($1 | ($2<<23) | ($4<<18)); } | OP_BF_FRA_FRB CR ',' FPR ',' FPR { emit4($1 | ($2<<23) | ($4<<16) | ($6<<11)); } | OP_BF_L_RA_RB CR ',' u1 ',' GPR ',' GPR { emit4($1 | ($2<<23) | ($4<<21) | ($6<<16) | ($8<<11)); } - | OP_BF_L_RA_SI CR ',' u1 ',' GPR ',' e16 { emit4($1 | ($2<<23) | ($4<<21) | ($6<<16) | $8); } - | OP_BF_L_RA_UI CR ',' u1 ',' GPR ',' e16 { emit4($1 | ($2<<23) | ($4<<21) | ($6<<16) | $8); } + | OP_BF_L_RA_SI CR ',' u1 ',' GPR ',' e16 { emit_hl($1 | ($2<<23) | ($4<<21) | ($6<<16) | $8); } + | OP_BF_L_RA_UI CR ',' u1 ',' GPR ',' e16 { emit_hl($1 | ($2<<23) | ($4<<21) | ($6<<16) | $8); } + | OP_BF_RA_RB cr_opt GPR ',' GPR { emit4($1 | ($2<<23) | ($3<<16) | ($5<<11)); } + | OP_BF_RA_SI cr_opt GPR ',' e16 { emit_hl($1 | ($2<<23) | ($3<<16) | $5); } + | OP_BF_RA_UI cr_opt GPR ',' e16 { emit_hl($1 | ($2<<23) | ($3<<16) | $5); } | OP_BF_U_C c CR ',' u4 { emit4($1 | $2 | ($3<<23) | ($5<<12)); } + | OP_BH { emit4($1); } + | OP_BH u2 { emit4($1 | ($2<<11)); } + | OP_BI_BDA u5 ',' bda { emit4($1 | ($2<<16) | $4); } + | OP_BI_BDL u5 ',' bdl { emit4($1 | ($2<<16) | $4); } + | OP_BI_BH u5 opt_bh { emit4($1 | ($2<<16) | $3); } + | OP_BICR_BDA cr_opt bda { emit4($1 | ($2<<18) | $3); } + | OP_BICR_BDL cr_opt bdl { emit4($1 | ($2<<18) | $3); } + | OP_BICR_BH { emit4($1); } + | OP_BICR_BH CR opt_bh { emit4($1 | ($2<<18) | $3); } | OP_BO_BI_BDA u5 ',' u5 ',' bda { emit4($1 | ($2<<21) | ($4<<16) | $6); } | OP_BO_BI_BDL u5 ',' u5 ',' bdl { emit4($1 | ($2<<21) | ($4<<16) | $6); } - | OP_BO_BI_BH u5 ',' u5 ',' u2 { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } + | OP_BO_BI_BH u5 ',' u5 opt_bh { emit4($1 | ($2<<21) | ($4<<16) | $5); } + | OP_BT_BA_BA u5 ',' u5 { emit4($1 | ($2<<21) | ($4<<16) | ($4<<11)); } | OP_BT_BA_BB u5 ',' u5 ',' u5 { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } + | OP_BT_BT_BT u5 { emit4($1 | ($2<<21) | ($2<<16) | ($2<<11)); } | OP_BT_C c u5 { emit4($1 | $2 | ($3<<21)); } | OP_FLM_FRB_C c u8 ',' FPR { emit4($1 | $2 | ($3<<17) | ($5<<11)); } - | OP_FRS_RA_D FPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } + | OP_FRS_RA_D FPR ',' e16 '(' GPR ')' { emit_hl($1 | ($2<<21) | ($6<<16) | $4); } | OP_FRS_RA_RB FPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_FRT_FRA_FRB_C c FPR ',' FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<11)); } - | OP_FRT_FRA_FRC_FRB_C c FPR ',' FPR ',' FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($9<<11) | ($7<<6)); } + | OP_FRT_FRA_FRC_FRB_C c FPR ',' FPR ',' FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($9<<11) | ($7<<6)); } | OP_FRT_FRA_FRC_C c FPR ',' FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<6)); } - | OP_FRT_FRB_C c FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<11)); } - | OP_FRT_RA_D FPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } + | OP_FRT_FRB_C c FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<11)); } + | OP_FRT_RA_D FPR ',' e16 '(' GPR ')' { emit_hl($1 | ($2<<21) | ($6<<16) | $4); } | OP_FRT_RA_RB FPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_FRT_C c FPR { emit4($1 | $2 | ($3<<21)); } + | OP_RA_RS_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16)); } + | OP_RA_RS_RB_C c GPR ',' GPR ',' GPR + { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); } + | OP_RA_RS_RB_MB5_ME5_C c GPR ',' GPR ',' GPR ',' u5 ',' u5 + { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | + ($9<<6) | ($11<<1)); } + | OP_RA_RS_RB_MB6_C c GPR ',' GPR ',' GPR ',' u6 + { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | MB6($9)); } + | OP_RA_RS_SH5_C c GPR ',' GPR ',' u5 + { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); } + | OP_RA_RS_SH5_MB5_ME5_C c GPR ',' GPR ',' u5 ',' u5 ',' u5 + { emit4($1 | $2 | ($5<<21) | ($3<<16) | + ($7<<11) | ($9<<6) | ($11<<1)); } + | OP_RA_RS_SH6_C c GPR ',' GPR ',' u6 + { emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($7)); } + | OP_RA_RS_SH6_MB6_C c GPR ',' GPR ',' u6 ',' u6 + { emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($7) | MB6($9)); } + | OP_RA_RS_UI GPR ',' GPR ',' e16 { emit_hl($1 | ($4<<21) | ($2<<16) | $6); } + | OP_RA_RS_UI_CC C GPR ',' GPR ',' e16 { emit_hl($1 | ($5<<21) | ($3<<16) | $7); } | OP_RT GPR { emit4($1 | ($2<<21)); } | OP_RT_RA_C c GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($5<<16)); } - | OP_RT_RA_D GPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } - | OP_RT_RA_DS GPR ',' ds '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } + | OP_RT_RA_D GPR ',' e16 '(' GPR ')' { emit_hl($1 | ($2<<21) | ($6<<16) | $4); } + | OP_RT_RA_DS GPR ',' ds '(' GPR ')' { emit_hl($1 | ($2<<21) | ($6<<16) | $4); } | OP_RT_RA_NB GPR ',' GPR ',' nb { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_RT_RA_RB GPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } - | OP_RT_RA_RB_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<11)); } - | OP_RT_RA_SI GPR ',' GPR ',' e16 { emit4($1 | ($2<<21) | ($4<<16) | $6); } - | OP_RT_RA_SI_addic c GPR ',' GPR ',' e16 { emit4($1 | ($2<<26) | ($3<<21) | ($5<<16) | $7); } - | OP_RT_SPR GPR ',' SPR { emit4($1 | ($2<<21) | ($4<<11)); } + | OP_RT_RA_RB_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<11)); } + | OP_RT_RA_SI GPR ',' GPR ',' e16 { emit_hl($1 | ($2<<21) | ($4<<16) | $6); } + | OP_RT_RA_SI_addic c GPR ',' GPR ',' e16 { emit_hl($1 | ($2<<26) | ($3<<21) | ($5<<16) | $7); } + | OP_RT_RA_SI_subi GPR ',' GPR ',' negate16 { emit4($1 | ($2<<21) | ($4<<16) | $6); } + | OP_RT_RA_SI_subic c GPR ',' GPR ',' negate16 { emit4($1 | ($2<<26) | ($3<<21) | ($5<<16) | $7); } + | OP_RT_RB_RA_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($7<<16) | ($5<<11)); } + | OP_RT_SI GPR ',' e16 { emit_hl($1 | ($2<<21) | $4); } + | OP_RT_SPR GPR ',' spr_num { emit4($1 | ($2<<21) | ($4<<11)); } | OP_RS_FXM u7 ',' GPR { emit4($1 | ($4<<21) | ($2<<12)); } - | OP_RS_RA_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16)); } - | OP_RS_RA_D GPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } - | OP_RS_RA_DS GPR ',' ds '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } + | OP_RS_RA_D GPR ',' e16 '(' GPR ')' { emit_hl($1 | ($2<<21) | ($6<<16) | $4); } + | OP_RS_RA_DS GPR ',' ds '(' GPR ')' { emit_hl($1 | ($2<<21) | ($6<<16) | $4); } | OP_RS_RA_NB GPR ',' GPR ',' nb { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } - | OP_RS_RA_UI GPR ',' GPR ',' e16 { emit4($1 | ($4<<21) | ($2<<16) | $6); } - | OP_RS_RA_UI_CC C GPR ',' GPR ',' e16 { emit4($1 | ($5<<21) | ($3<<16) | $7); } | OP_RS_RA_RB GPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_RS_RA_RB_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); } | OP_RS_RA_RA_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($5<<11)); } - | OP_RS_RA_RB_MB5_ME5_C c GPR ',' GPR ',' GPR ',' u5 ',' u5 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | ($9<<6) | ($11<<1)); } - | OP_RS_RA_RB_MB6_C c GPR ',' GPR ',' GPR ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | (($9&0x1F)<<6) | (($9&0x20)>>0)); } - | OP_RS_RA_RB_ME6_C c GPR ',' GPR ',' GPR ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | (($9&0x1F)<<6) | (($9&0x20)>>0)); } - | OP_RS_RA_SH_MB5_ME5_C c GPR ',' GPR ',' u5 ',' u5 ',' u5 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | ($9<<6) | ($11<<1)); } - | OP_RS_RA_SH_MB6_SH_C c GPR ',' GPR ',' u6 ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | (($7&0x1F)<<11) | ($9<<6) | (($7&0x20)>>4)); } - | OP_RS_RA_SH_ME6_SH_C c GPR ',' GPR ',' u6 ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | (($7&0x1F)<<11) | ($9<<6) | (($7&0x20)>>4)); } - | OP_RS_RA_SH5_C c GPR ',' GPR ',' u5 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); } - | OP_RS_RA_SH6_C c GPR ',' GPR ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | (($7&0x1F)<<11) | (($7&0x20)>>4)); } - | OP_RS_SPR SPR ',' GPR { emit4($1 | ($4<<21) | ($2<<11)); } + | OP_RS_SPR spr_num ',' GPR { emit4($1 | ($4<<21) | ($2<<11)); } | OP_TO_RA_RB u5 ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } - | OP_TO_RA_SI u5 ',' GPR ',' e16 { emit4($1 | ($2<<21) | ($4<<16) | $6); } + | OP_TO_RA_SI u5 ',' GPR ',' e16 { emit_hl($1 | ($2<<21) | ($4<<16) | $6); } + | OP_TOX_RA_RB GPR ',' GPR { emit4($1 | ($2<<16) | ($4<<11)); } + | OP_TOX_RA_SI GPR ',' e16 { emit_hl($1 | ($2<<16) | $4); } + | OP_LEV { emit4($1); } | OP_LEV u7 { emit4($1 | ($2<<5)); } | OP_LIA lia { emit4($1 | $2); } | OP_LIL lil { emit4($1 | $2); } | OP_LI32 li32 /* emitted in subrule */ + | OP_clrlsldi c GPR ',' GPR ',' u6 ',' u6 + { + word_t mb = ($7 - $9) & 0x3f; + fit($9 <= $7); + emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($9) | MB6(mb)); + } + | OP_clrldi c GPR ',' GPR ',' u6 + { + emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(0) | MB6($7)); + } + | OP_clrrdi c GPR ',' GPR ',' u6 + { + word_t me = 63 - $7; + emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(0) | MB6(me)); + } + | OP_extldi c GPR ',' GPR ',' u6 ',' u6 + { + word_t me = ($7 - 1) & 0x3f; + fit($7 > 0); + emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($9) | MB6(me)); + } + | OP_extrdi c GPR ',' GPR ',' u6 ',' u6 + { + word_t sh = ($9 + $7) & 0x3f; + word_t mb = (64 - $7) & 0x3f; + fit($7 > 0); + emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(sh) | MB6(mb)); + } + | OP_rotrdi c GPR ',' GPR ',' u6 + { + word_t sh = (64 - $7) & 0x3f; + emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(sh) | MB6(0)); + } + | OP_sldi c GPR ',' GPR ',' u6 + { + word_t me = 63 - $7; + emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($7) | MB6(me)); + } + | OP_srdi c GPR ',' GPR ',' u6 + { + word_t sh = (64 - $7) & 0x3f; + emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(sh) | MB6($7)); + } + | OP_clrlslwi c GPR ',' GPR ',' u5 ',' u5 + { + word_t mb = ($7 - $9) & 0x1f; + word_t me = 31 - $9; + fit($9 <= $7); + emit4($1 | $2 | ($5<<21) | ($3<<16) | + ($9<<11) | (mb<<6) | (me<<1)); + } + | OP_clrlwi c GPR ',' GPR ',' u5 + { + emit4($1 | $2 | ($5<<21) | ($3<<16) | + (0<<11) | ($7<<6) | (31<<1)); + } + | OP_clrrwi c GPR ',' GPR ',' u5 + { + word_t me = 31 - $7; + emit4($1 | $2 | ($5<<21) | ($3<<16) | + (0<<11) | (0<<6) | (me<<1)); + } + | OP_extlwi c GPR ',' GPR ',' u5 ',' u5 + { + word_t me = ($7 - 1) & 0x1f; + fit($7 > 0); + emit4($1 | $2 | ($5<<21) | ($3<<16) | + ($9<<11) | (0<<6) | (me<<1)); + } + | OP_extrwi c GPR ',' GPR ',' u5 ',' u5 + { + word_t sh = ($9 + $7) & 0x1f; + word_t mb = (32 - $7) & 0x1f; + fit($7 > 0); + emit4($1 | $2 | ($5<<21) | ($3<<16) | + (sh<<11) | (mb<<6) | (31<<1)); + } + | OP_inslwi c GPR ',' GPR ',' u5 ',' u5 + { + word_t sh = (32 - $9) & 0x1f; + word_t me = ($9 + $7 - 1) & 0x1f; + fit($7 > 0); + emit4($1 | $2 | ($5<<21) | ($3<<16) | + (sh<<11) | ($9<<6) | (me<<1)); + } + | OP_insrwi c GPR ',' GPR ',' u5 ',' u5 + { + word_t sh = (32 - $9 - $7) & 0x1f; + word_t me = ($9 + $7 - 1) & 0x1f; + fit($7 > 0); + emit4($1 | $2 | ($5<<21) | ($3<<16) | + (sh<<11) | ($9<<6) | (me<<1)); + } + | OP_rotrwi c GPR ',' GPR ',' u5 + { + word_t sh = (32 - $7) & 0x1f; + emit4($1 | $2 | ($5<<21) | ($3<<16) | + (sh<<11) | (0<<6) | (31<<1)); + } + | OP_slwi c GPR ',' GPR ',' u5 + { + word_t me = 31 - $7; + emit4($1 | $2 | ($5<<21) | ($3<<16) | + ($7<<11) | (0<<6) | (me<<1)); + } + | OP_srwi c GPR ',' GPR ',' u5 + { + word_t sh = (32 - $7) & 0x1f; + emit4($1 | $2 | ($5<<21) | ($3<<16) | + (sh<<11) | ($7<<6) | (31<<1)); + } ; c : /* nothing */ { $$ = 0; } | C { $$ = 1; } ; - + e16 : absexp { @@ -74,9 +217,24 @@ e16 if (($1 < -0x8000) || ($1 > 0xffff)) serror("16-bit value out of range"); $$ = (uint16_t) $1; + no_hl(); + } + | OP_HI ASC_LPAR expr ASC_RPAR { $$ = eval_hl(&$3, OP_HI); } + | OP_HA ASC_LPAR expr ASC_RPAR { $$ = eval_hl(&$3, OP_HA); } + | OP_LO ASC_LPAR expr ASC_RPAR { $$ = eval_hl(&$3, OP_LO); } + ; + +negate16 + : absexp + { + /* To encode subi, we negate the immediate value, then + * it must fit as signed 16-bit. */ + $$ = -$1; + fit(fitx($$, 16)); + $$ = (uint16_t) $$; } ; - + u8 : absexp { @@ -85,7 +243,7 @@ u8 $$ = $1; } ; - + u7 : absexp { @@ -94,7 +252,7 @@ u7 $$ = $1; } ; - + u6 : absexp { @@ -103,7 +261,7 @@ u6 $$ = $1; } ; - + u5 : absexp { @@ -112,7 +270,7 @@ u5 $$ = $1; } ; - + u4 : absexp { @@ -121,7 +279,7 @@ u4 $$ = $1; } ; - + u1 : absexp { @@ -130,7 +288,7 @@ u1 $$ = $1; } ; - + u2 : absexp { @@ -139,7 +297,20 @@ u2 $$ = $1; } ; - + +/* Optional comma, branch hint. */ +opt_bh + : /* nothing */ { $$ = 0; } + | ',' u2 { $$ = ($2<<11); } + +/* + * Optional condition register, comma. This checks if the token is a + * CR register name. This wouldn't work if we allowed CR as a number. + */ +cr_opt + : /* nothing */ { $$ = 0; } + | CR ',' { $$ = $1; } + ds : e16 { @@ -148,26 +319,26 @@ ds $$ = $1; } ; - + nb : absexp { if (($1 < 1) || ($1 > 32)) serror("register count must be in the range 1..32"); - + if ($1 == 32) $$ = 0; else - $$ = $1; + $$ = $1; } ; - + bdl : expr { int dist = $1.val - DOTVAL; fit(fitx(dist, 25)); - + if (dist & 0x3) serror("jump targets must be 4-aligned"); @@ -183,7 +354,7 @@ bda { int target = $1.val; fit(fitx(target, 16)); - + if (target & 0x3) serror("jump targets must be 4-aligned"); @@ -193,12 +364,12 @@ bda $$ = target & 0xFFFD; } ; - + li32 : GPR ',' expr { - quad type = $3.typ & S_TYP; - quad val = $3.val; + word_t type = $3.typ & S_TYP; + word_t val = $3.val; if ((type == S_ABS) && (val <= 0xffff)) emit4((14<<26) | ($1<<21) | (0<<16) | val); /* addi */ else @@ -215,7 +386,7 @@ lil { int dist = $1.val - DOTVAL; fit(fitx(dist, 26)); - + if (dist & 0x3) serror("jump targets must be 4-aligned"); @@ -223,13 +394,13 @@ lil $$ = dist & 0x03FFFFFD; } ; - + lia : expr { int target = $1.val; fit(fitx(target, 26)); - + if (target & 0x3) serror("jump targets must be 4-aligned"); @@ -237,4 +408,14 @@ lia $$ = target & 0x03FFFFFD; } ; - + +spr_num + : SPR { $$ = $1; } + | absexp + { + if (($1 < 0) || ($1 > 0x3ff)) + serror("spr number out of range"); + /* mfspr, mtspr swap the low and high 5 bits */ + $$ = ($1 >> 5) | (($1 & 0x1f) << 5); + } + ; diff --git a/mach/powerpc/as/mach5.c b/mach/powerpc/as/mach5.c index 998cd8d9c..d72b8514a 100644 --- a/mach/powerpc/as/mach5.c +++ b/mach/powerpc/as/mach5.c @@ -1,5 +1,75 @@ -/* - * $Source$ - * $State$ - */ +static int hl_token; +static expr_t hl_expr; +void no_hl(void) { + hl_token = 0; +} + +word_t eval_hl(expr_t* expr, int token) +{ + word_t val = expr->val; + uint16_t hi = val >> 16; + uint16_t lo = val & 0xffff; + + hl_token = token; + hl_expr = *expr; + + switch (token) { + case OP_HI: /* hi16[expr] */ + return hi; + case OP_HA: /* ha16[expr]*/ + /* + * If the low half will be treated as a signed value, + * then values greater than 0x7fff will cause the high + * half to have 1 subtracted from it; so we apply an + * adjustment here. + */ + if (lo > 0x7fff) + hi++; + return hi; + case OP_LO: /* lo16[expr] */ + return lo; + } +} + +void emit_hl(word_t in) +{ + word_t reg; + int type; + + switch (hl_token) { + case OP_HI: /* hi16[expr] */ + case OP_HA: /* ha16[expr] */ + if (PASS_RELO && (hl_expr.typ & S_TYP) != S_ABS) { + /* + * RELOLIS only works with lis _, _ (same as + * addis _, r0, _). Check if instruction + * isn't addis or register RA isn't r0. + */ + if ((in & 0xfc1f0000) != (0x3c000000)) + serror("relocation only works with lis"); + + /* + * High bit: ha16 flag + * Next 5 bits: register RT + * Low 26 bits: signed offset + */ + fit(fitx(hl_expr.val, 26)); + newrelo(hl_expr.typ, RELOLIS | FIXUPFLAGS); + reg = (in >> 21) & 0x1f; + in = (hl_token == OP_HA) << 31; + in |= reg << 26; + in |= hl_expr.val & 0x03ffffff; + } + break; + case OP_LO: /* lo16[expr] */ + if (PASS_RELO && (hl_expr.typ & S_TYP) != S_ABS) { + DOTVAL += 2; + newrelo(hl_expr.typ, RELO2 | FIXUPFLAGS); + DOTVAL -= 2; + } + break; + } + + emit4(in); +} diff --git a/mach/powerpc/libem/aar4.s b/mach/powerpc/libem/aar4.s index 2c65af643..5e4155091 100644 --- a/mach/powerpc/libem/aar4.s +++ b/mach/powerpc/libem/aar4.s @@ -1,12 +1,5 @@ -# -! $Source$ -! $State$ -! $Revision$ - -#include "powerpc.h" - .sect .text - + ! Index into a bounds-checked array. ! ! On entry: @@ -20,19 +13,20 @@ .define .aar4 .aar4: - li32 r0, .trap_earray + lis r0, hi16[.trap_earray] + ori r0, r0, lo16[.trap_earray] mtspr ctr, r0 ! load CTR with trap address lwz r0, 0(r3) subf. r4, r0, r4 ! adjust range - bcctr IFTRUE, LT, 0 ! check lower bound - + bltctr ! check lower bound + lwz r0, 4(r3) - cmpl cr0, 0, r4, r3 - bcctr IFFALSE, LT, 0 ! check upper bound - + cmplw r4, r3 + bgectr ! check upper bound + lwz r0, 8(r3) mullw r4, r4, r0 ! scale index add r3, r4, r5 ! calculate element address - - bclr ALWAYS, 0, 0 + + blr diff --git a/mach/powerpc/libem/and.s b/mach/powerpc/libem/and.s new file mode 100644 index 000000000..cb4e1e54a --- /dev/null +++ b/mach/powerpc/libem/and.s @@ -0,0 +1,24 @@ +.sect .text + +! Set intersection. +! Stack: ( b a size -- a*b ) + +.define .and +.and: + lwz r3, 0 (sp) ! r3 = size + addi sp, sp, 4 + + mr r4, sp ! r4 = ptr to set a + add r5, sp, r3 ! r5 = ptr to set b + srwi r6, r3, 2 + mtspr ctr, r6 ! ctr = r3 / 4 +1: + lwz r7, 0(r4) + lwz r8, 0(r5) + and r8, r7, r8 ! intersection of words + stw r8, 0(r5) + addi r4, r4, 4 + addi r5, r5, 4 + bdnz 1b ! loop ctr times + add sp, sp, r3 + blr diff --git a/mach/powerpc/libem/build.lua b/mach/powerpc/libem/build.lua index 318be381d..466a28fb3 100644 --- a/mach/powerpc/libem/build.lua +++ b/mach/powerpc/libem/build.lua @@ -1,14 +1,12 @@ for _, plat in ipairs(vars.plats) do acklibrary { name = "headers_"..plat, - hdrs = { "./*.h" } } acklibrary { name = "lib_"..plat, srcs = { "./*.s", - "./*.e", }, vars = { plat = plat }, deps = { diff --git a/mach/powerpc/libem/cfi8.s b/mach/powerpc/libem/cfi8.s index 7142c694b..9a87e99ae 100644 --- a/mach/powerpc/libem/cfi8.s +++ b/mach/powerpc/libem/cfi8.s @@ -1,10 +1,3 @@ -# -! $Source$ -! $State$ -! $Revision$ - -#include "powerpc.h" - .sect .text ! Converts a 64-bit double into a 32-bit integer. @@ -17,4 +10,4 @@ fctiwz f0, f0 stfd f0, 0(sp) addi sp, sp, 4 - bclr ALWAYS, 0, 0 ! ...and return + blr diff --git a/mach/powerpc/libem/cfu8.s b/mach/powerpc/libem/cfu8.s index 758df8572..915f84dd2 100644 --- a/mach/powerpc/libem/cfu8.s +++ b/mach/powerpc/libem/cfu8.s @@ -1,10 +1,3 @@ -# -! $Source$ -! $State$ -! $Revision$ - -#include "powerpc.h" - .sect .text ! Converts a 64-bit double into a 32-bit unsigned integer. @@ -13,17 +6,17 @@ .define .cfu8 .cfu8: - li32 r3, .fd_00000000 - lfd f0, 0(r3) ! f0 = 0.0 - + lis r3, ha16[.fd_00000000] + lfd f0, lo16[.fd_00000000](r3) ! f0 = 0.0 + lfd f1, 0(sp) ! value to be converted - li32 r3, .fd_FFFFFFFF - lfd f3, 0(r3) ! f3 = 0xFFFFFFFF + lis r3, ha16[.fd_FFFFFFFF] + lfd f3, lo16[.fd_FFFFFFFF](r3) ! f3 = 0xFFFFFFFF + + lis r3, ha16[.fd_80000000] + lfd f4, lo16[.fd_80000000](r3) ! f4 = 0x80000000 - li32 r3, .fd_80000000 - lfd f4, 0(r3) ! f4 = 0x80000000 - fsel f2, f1, f1, f0 fsub f5, f3, f1 fsel f2, f5, f2, f3 @@ -34,11 +27,11 @@ stfd f2, 0(sp) addi sp, sp, 4 - - bclr IFTRUE, LT, 0 - + + bltlr + lwz r3, 0(sp) xoris r3, r3, 0x8000 stw r3, 0(sp) - bclr ALWAYS, 0, 0 + blr diff --git a/mach/powerpc/libem/cif8.s b/mach/powerpc/libem/cif8.s index d2c82e54e..13abbcade 100644 --- a/mach/powerpc/libem/cif8.s +++ b/mach/powerpc/libem/cif8.s @@ -1,9 +1,4 @@ -# -! $Source$ -! $State$ -! $Revision$ - -#include "powerpc.h" +.sect .text; .sect .rom; .sect .data; .sect .bss .sect .text @@ -14,22 +9,22 @@ .define .cif8 .cif8: addi sp, sp, -4 ! make space for the double - + lwz r3, 4(sp) xoris r3, r3, 0x8000 stw r3, 4(sp) ! flip sign of integer value - + addis r3, r0, 0x4330 stw r3, 0(sp) ! set high word to construct a double - + lfd f0, 0(sp) ! load value - li32 r3, pivot - lfd f1, 0(r3) ! load pivot value + lis r3, ha16[pivot] + lfd f1, lo16[pivot](r3) ! load pivot value fsub f0, f0, f1 ! adjust - + stfd f0, 0(sp) ! save value again... - bclr ALWAYS, 0, 0 ! ...and return + blr ! ...and return .sect .rom pivot: diff --git a/mach/powerpc/libem/cms.s b/mach/powerpc/libem/cms.s new file mode 100644 index 000000000..30aaccd20 --- /dev/null +++ b/mach/powerpc/libem/cms.s @@ -0,0 +1,30 @@ +.sect .text + +! Compare sets a, b. +! Stack: ( b a -- ) +! With r3 = size of each set +! Yields r3 = 0 if equal, nonzero if not equal + +.define .cms +.cms: + mr r4, sp ! r4 = ptr to set a + add r5, sp, r3 ! r5 = ptr to set b + mr r6, r3 ! r6 = size + srwi r3, r3, 2 + mtspr ctr, r3 ! ctr = size / 4 +1: + lwz r7, 0(r4) + lwz r8, 0(r5) + cmpw cr0, r7, r8 ! compare words in sets + addi r4, r4, 4 + addi r5, r5, 4 + bne cr0, 2f ! branch if not equal + bdnz 1b ! loop ctr times + addi r3, r0, 0 ! equal: return 0 + b 3f +2: + addi r3, r0, 1 ! not equal: return 1 +3: + slwi r6, r6, 1 ! r6 = size * 2 + add sp, sp, r6 ! remove sets from stack + blr diff --git a/mach/powerpc/libem/com.s b/mach/powerpc/libem/com.s new file mode 100644 index 000000000..3168cfe17 --- /dev/null +++ b/mach/powerpc/libem/com.s @@ -0,0 +1,20 @@ +.sect .text + +! Set complement. +! Stack: ( a size -- ~a ) + +.define .com +.com: + lwz r3, 0 (sp) ! size + addi sp, sp, 4 + + mr r4, sp ! r4 = pointer to set a + srwi r5, r3, 2 + mtspr ctr, r5 ! ctr = r3 / 4 +1: + lwz r6, 0(r4) + nor r6, r6, r6 ! complement of word + stw r6, 0(r4) + addi r4, r4, 4 + bdnz 1b ! loop ctr times + blr diff --git a/mach/powerpc/libem/csa.s b/mach/powerpc/libem/csa.s index 88e6e176a..3898241c4 100644 --- a/mach/powerpc/libem/csa.s +++ b/mach/powerpc/libem/csa.s @@ -1,10 +1,3 @@ -# -! $Source$ -! $State$ -! $Revision$ - -#include "powerpc.h" - .sect .text ! this is not a subroutine, but just a @@ -25,23 +18,17 @@ lwz r5, 4(r3) ! fetch lower bound subf. r4, r5, r4 ! adjust value - bcctr IFTRUE, LT, 0 ! jump to default if out of range - + bltctr ! jump to default if out of range + lwz r5, 8(r3) ! fetch range - cmp cr0, 0, r4, r5 - bcctr IFTRUE, GT, 0 ! jump to default if out of range - + cmplw r4, r5 + bgtctr ! jump to default if out of range + addi r3, r3, 12 ! skip header - rlwinm r4, r4, 2, 0, 31-2 ! scale value (<<2) - b 1f -1: + slwi r4, r4, 2 ! scale value (<<2) lwzx r5, r3, r4 ! load target - b 1f -1: mtspr ctr, r5 - + or. r5, r5, r5 ! test it - b 1f -1: - bcctr IFFALSE, EQ, 0 ! jump to target if non-zero + bnectr ! jump to target if non-zero b .trap_ecase ! otherwise trap diff --git a/mach/powerpc/libem/csb.s b/mach/powerpc/libem/csb.s index a8df85d7f..571bfc210 100644 --- a/mach/powerpc/libem/csb.s +++ b/mach/powerpc/libem/csb.s @@ -1,10 +1,3 @@ -# -! $Source$ -! $State$ -! $Revision$ - -#include "powerpc.h" - .sect .text ! this is not a subroutine, but just a @@ -22,21 +15,21 @@ lwz r5, 0(r3) ! load default mtspr ctr, r5 - + lwz r6, 4(r3) ! fetch count - + 1: or. r6, r6, r6 ! test count - bcctr IFTRUE, EQ, 0 ! exit if zero + beqctr ! exit if zero addi r6, r6, -1 ! otherwise decrement - + lwzu r7, 8(r3) ! fetch target index, increment pointer - cmp cr0, 0, r4, r7 ! compare with value - bc IFFALSE, EQ, 1b ! if not equal, go again - + cmpw r4, r7 ! compare with value + bne 1b ! if not equal, go again + lwz r7, 4(r3) ! fetch target address mtspr ctr, r7 - + or. r7, r7, r7 ! test it - bcctr IFFALSE, EQ, 0 ! jump to target if non-zero + bnectr ! jump to target if non-zero b .trap_ecase ! otherwise trap diff --git a/mach/powerpc/libem/cuf8.s b/mach/powerpc/libem/cuf8.s index 5d5a12988..ce9932aa1 100644 --- a/mach/powerpc/libem/cuf8.s +++ b/mach/powerpc/libem/cuf8.s @@ -1,10 +1,3 @@ -# -! $Source$ -! $State$ -! $Revision$ - -#include "powerpc.h" - .sect .text ! Converts a 32-bit unsigned integer into a 64-bit double. @@ -14,18 +7,18 @@ .define .cuf8 .cuf8: addi sp, sp, -4 ! make space for the double - - addis r3, r0, 0x4330 + + lis r3, 0x4330 stw r3, 0(sp) ! set high word to construct a double - + lfd f0, 0(sp) ! load value - - li32 r3, pivot - lfd f1, 0(r3) ! load pivot value + + lis r3, ha16[pivot] + lfd f1, lo16[pivot](r3) ! load pivot value fsub f0, f0, f1 ! adjust - + stfd f0, 0(sp) ! save value again... - bclr ALWAYS, 0, 0 ! ...and return + blr ! ...and return .sect .rom pivot: diff --git a/mach/powerpc/libem/fd_00000000.s b/mach/powerpc/libem/fd_00000000.s index cefa91b8e..8ffe44a24 100644 --- a/mach/powerpc/libem/fd_00000000.s +++ b/mach/powerpc/libem/fd_00000000.s @@ -1,10 +1,5 @@ -# -! $Source$ -! $State$ -! $Revision$ +.sect .text; .sect .rom; .sect .data; .sect .bss -#include "powerpc.h" - .sect .rom ! Contains a handy double-precision zero. (Also works as a single-precision diff --git a/mach/powerpc/libem/fd_80000000.s b/mach/powerpc/libem/fd_80000000.s index 50eacd586..5c153bba8 100644 --- a/mach/powerpc/libem/fd_80000000.s +++ b/mach/powerpc/libem/fd_80000000.s @@ -1,10 +1,5 @@ -# -! $Source$ -! $State$ -! $Revision$ +.sect .text; .sect .rom; .sect .data; .sect .bss -#include "powerpc.h" - .sect .rom ! Contains a handy double-precision 0x80000000. diff --git a/mach/powerpc/libem/fd_FFFFFFFF.s b/mach/powerpc/libem/fd_FFFFFFFF.s index 9218f2726..88cf04bd9 100644 --- a/mach/powerpc/libem/fd_FFFFFFFF.s +++ b/mach/powerpc/libem/fd_FFFFFFFF.s @@ -1,15 +1,10 @@ -# -! $Source$ -! $State$ -! $Revision$ +.sect .text; .sect .rom; .sect .data; .sect .bss -#include "powerpc.h" - .sect .rom ! Contains a handy double-precision 0xFFFFFFFF. .define .fd_FFFFFFFF -.fd_FFFFFFFF: +.fd_FFFFFFFF: !float 4.294967295e+9 sz 8 .data1 0101,0357,0377,0377,0377,0340,00,00 diff --git a/mach/powerpc/libem/fef8.s b/mach/powerpc/libem/fef8.s index fc72b04f2..f71ab8e38 100644 --- a/mach/powerpc/libem/fef8.s +++ b/mach/powerpc/libem/fef8.s @@ -1,4 +1,4 @@ -#include "powerpc.h" +.sect .text; .sect .rom; .sect .data; .sect .bss .sect .text @@ -10,46 +10,44 @@ ! r3 = fraction, high word (bits 0..31) ! r4 = fraction, low word (bits 32..63) ! r5 = exponent -! Kills: cr0 f0 f1 r6 r7 .define .fef8 .fef8: ! IEEE double-precision format: ! sign exponent fraction ! 0 1..11 12..63 - rlwinm r6, r3, 12, 21, 31 ! r6 = IEEE exponent - addis r7, r0, 0x7ff0 ! r7 = exponent mask + extrwi r6, r3, 11, 1 ! r6 = IEEE exponent addi r5, r6, -1022 ! r5 = true exponent - cmpi cr0, 0, r6, 2047 - bclr IFTRUE, EQ, 0 ! return if infinity or NaN - cmpi cr0, 0, r6, 0 - bc IFFALSE, EQ, 1f ! jump if normalized number + cmpwi r6, 2047 + beqlr ! return if infinity or NaN + cmpwi r6, 0 + bne 1f ! jump if normalized number ! Got denormalized number or zero, probably zero. - rlwinm r6, r3, 0, 12, 31 + extrwi r6, r3, 22, 12 addi r5, r0, 0 ! r5 = true exponent = 0 or. r6, r6, r4 ! r6 = high|low fraction - bclr IFTRUE, EQ, 0 ! return if zero + beqlr ! return if zero ! Got denormalized number, not zero. stwu r4, -4(sp) stwu r3, -4(sp) - li32 r6, _2_64 lfd f0, 0(sp) - lfd f1, 0(r6) + lis r6, ha16[_2_64] + lfd f1, lo16[_2_64](r6) fmul f0, f0, f1 ! multiply it by 2**64 stfd f0, 0(sp) lwz r3, 0(sp) lwz r4, 4(sp) - rlwinm r6, r3, 12, 21, 31 ! r6 = IEEE exponent + extrwi r6, r3, 11, 1 ! r6 = IEEE exponent addi sp, sp, 8 addi r5, r6, -1022 - 64 ! r5 = true exponent 1: ! Put fraction in [0.5, 1) or (-1, -0.5] by setting its ! exponent to true 0, IEEE 1022. - andc r3, r3, r7 ! clear old exponent + rlwinm r3, r3, 0, 12, 0 ! clear old exponent oris r3, r3, 1022 << 4 ! set new exponent - bclr ALWAYS, 0, 0 + blr .sect .rom _2_64: diff --git a/mach/powerpc/libem/fif8.s b/mach/powerpc/libem/fif8.s index a26c77830..eda9b04f2 100644 --- a/mach/powerpc/libem/fif8.s +++ b/mach/powerpc/libem/fif8.s @@ -1,5 +1,3 @@ -#include "powerpc.h" - .sect .text ! Multiplies two double-precision floats, then splits the product into @@ -9,7 +7,6 @@ ! Yields: ! f1 = fraction ! f2 = integer -! Kills: cr0 f1 f2 r3 r4 r5 r6 .define .fif8 .fif8: @@ -25,17 +22,16 @@ ! 0 to 51, then the IEEE fraction has that many integer bits. ! (IEEE has an implicit 1 before its fraction. If the IEEE ! fraction has 0 integer bits, we still have an integer.) - rlwinm r5, r3, 12, 21, 31 ! r5 = IEEE exponent + extrwi r5, r3, 11, 1 ! r5 = IEEE exponent addic. r5, r5, -1023 ! r5 = nr of integer bits - bc IFTRUE, LT, no_int - cmpi cr0, 0, r5, 21 - bc IFTRUE, LT, small_int - cmpi cr0, 0, r5, 52 - bc IFTRUE, LT, big_int + blt no_int + cmpwi r5, 21 + blt small_int + cmpwi r5, 52 + blt big_int - ! f1 is an integer without fraction. Jump to calculate - ! fraction f1 = f2 - f1. It will be zero (or perhaps NaN). - fmr f2, f1 + ! f1 is an integer without fraction (or infinity or NaN). + fmr f2, f1 ! integer = f1 b subtract no_int: @@ -46,17 +42,17 @@ no_int: small_int: ! f1 has r5 = 0 to 20 integer bits in the IEEE fraction. ! High word has 20 - r5 fraction bits. - addi r6, r0, 20 + li r6, 20 subf r6, r5, r6 srw r3, r3, r6 - addi r4, r0, 0 ! clear low word + li r4, 0 ! clear low word slw r3, r3, r6 ! clear fraction in high word b move_int big_int: ! f1 has r5 = 21 to 51 to integer bits. ! Low word has 52 - r5 fraction bits. - addi r6, r0, 52 + li r6, 52 subf r6, r5, r6 srw r4, r4, r6 slw r4, r4, r6 ! clear fraction in low word @@ -68,4 +64,4 @@ subtract: fsub f1, f1, f2 ! fraction = value - integer done: addi sp, sp, 8 ! restore stack pointer - bclr ALWAYS, 0, 0 + blr diff --git a/mach/powerpc/libem/inn.s b/mach/powerpc/libem/inn.s index f5ae4c63e..8925e776e 100644 --- a/mach/powerpc/libem/inn.s +++ b/mach/powerpc/libem/inn.s @@ -1,4 +1,4 @@ -#include "powerpc.h" +# .sect .text @@ -13,14 +13,14 @@ lwz r4, 4(sp) /* r4 = bit number */ addi r5, sp, 8 /* r5 = base address of bit set */ - srawi r6, r4, 3 /* r6 = byte address into set */ - andi. r7, r4, 7 /* r7 = bit within byte */ + rlwinm r6, r4, 29, 3, 29 /* r6 = byte index of word in set */ + extrwi r7, r4, 5, 27 /* r7 = bit number within word */ - lbzx r8, r5, r6 /* r8 = individual byte from set */ - sraw r8, r8, r7 - rlwinm r8, r8, 0, 31, 31 + lwzx r8, r5, r6 /* r8 = individual word from set */ + srw r8, r8, r7 + extrwi r8, r8, 1, 31 addi sp, sp, 8 /* retract over the two words */ add sp, sp, r3 /* retract over bitfield */ stwu r8, -4(sp) /* push result */ - bclr ALWAYS, 0, 0 /* return */ + blr /* return */ diff --git a/mach/powerpc/libem/ior.s b/mach/powerpc/libem/ior.s new file mode 100644 index 000000000..e6cd1844e --- /dev/null +++ b/mach/powerpc/libem/ior.s @@ -0,0 +1,24 @@ +.sect .text + +! Set union. +! Stack: ( b a size -- a+b ) + +.define .ior +.ior: + lwz r3, 0 (sp) + addi sp, sp, 4 + + mr r4, sp ! r4 = ptr to set a + add r5, sp, r3 ! r5 = ptr to set b + srwi r6, r3, 2 + mtspr ctr, r6 ! ctr = r3 / 4 +1: + lwz r7, 0(r4) + lwz r8, 0(r5) + or r8, r7, r8 ! union of words + stw r8, 0(r5) + addi r4, r4, 4 + addi r5, r5, 4 + bdnz 1b ! loop ctr times + add sp, sp, r3 + blr diff --git a/mach/powerpc/libem/lar4.s b/mach/powerpc/libem/lar4.s index 6375979c4..2f5c3683c 100644 --- a/mach/powerpc/libem/lar4.s +++ b/mach/powerpc/libem/lar4.s @@ -1,6 +1,3 @@ -# -#include "powerpc.h" - .sect .text ! Load from bounds-checked array. @@ -18,19 +15,19 @@ ! r3 = ptr to element ! r0 = size of element - cmpi cr0, 0, r0, 1 - bc IFFALSE, EQ, 1f + cmpwi r0, 1 + bne 1f ! Load 1 byte. lbz r4, 0(r3) stwu r4, -4(sp) - bclr ALWAYS, 0, 0 + blr 1: - cmpi cr0, 0, r0, 2 - bc IFFALSE, EQ, 2f + cmpwi r0, 2 + bne 2f ! Load 2 bytes. lhz r4, 0(r3) stwu r4, -4(sp) - bclr ALWAYS, 0, 0 + blr 2: ! Load r0 bytes, where r0 must be a positive multiple of 4. subf sp, r0, sp ! move stack pointer down @@ -39,5 +36,5 @@ addic. r5, r5, -4 ! r5 -= 4 lwzx r4, r5, r3 stwx r4, r5, sp - bc IFTRUE, GT, 3b ! loop if r5 > 0 - bclr ALWAYS, 0, 0 + bgt 3b ! loop if r5 > 0 + blr diff --git a/mach/powerpc/libem/los.s b/mach/powerpc/libem/los.s index f867fe770..2d412bce8 100644 --- a/mach/powerpc/libem/los.s +++ b/mach/powerpc/libem/los.s @@ -1,10 +1,3 @@ -# -! $Source$ -! $State$ -! $Revision$ - -#include "powerpc.h" - .sect .text ! Loads a variable-sized structure onto the stack. @@ -15,32 +8,32 @@ .define .los .los: ! These sizes are handled specially. - - cmpi cr0, 0, r3, 1 - bc IFFALSE, GT, size1 - - cmpi cr0, 0, r3, 2 - bc IFFALSE, GT, size2 - - cmpi cr0, 0, r3, 4 - bc IFFALSE, GT, size4 - + + cmplwi r3, 1 + ble size1 + + cmplwi r3, 2 + ble size2 + + cmplwi r3, 4 + ble size4 + ! Variable-sized structure. - + addi r3, r3, 3 - andi. r3, r3, ~3 ! align size - + clrrwi r3, r3, 2 ! align size + add r4, r4, r3 ! adjust address to top of block - srawi r3, r3, 2 ! convert size to the number of words + srwi r3, r3, 2 ! convert size to the number of words mtspr ctr, r3 - + 1: lwzu r5, -4(r4) stwu r5, -4(sp) - bc DNZ, 0, 1b ! decrement CTR, jump if non-zero - bclr ALWAYS, 0, 0 - + bdnz 1b ! decrement CTR, jump if non-zero + blr + size1: lbz r3, 0(r4) b 1f @@ -51,4 +44,4 @@ size4: lwz r3, 0(r4) 1: stwu r3, -4(sp) - bclr ALWAYS, 0, 0 + blr diff --git a/mach/powerpc/libem/powerpc.h b/mach/powerpc/libem/powerpc.h deleted file mode 100644 index 3540a6856..000000000 --- a/mach/powerpc/libem/powerpc.h +++ /dev/null @@ -1,22 +0,0 @@ -# -! $Source$ -! $State$ -! $Revision$ - -! Declare segments (the order is important). - -.sect .text -.sect .rom -.sect .data -.sect .bss - -#define IFFALSE 4 -#define IFTRUE 12 -#define ALWAYS 20 -#define DNZ 16 - -#define LT 0 -#define GT 1 -#define EQ 2 -#define OV 3 - diff --git a/mach/powerpc/libem/rck.s b/mach/powerpc/libem/rck.s new file mode 100644 index 000000000..9008be610 --- /dev/null +++ b/mach/powerpc/libem/rck.s @@ -0,0 +1,20 @@ +.sect .text + +! Bounds check. Traps if the value is out of range. +! Stack: ( value descriptor -- value ) + +.define .rck +.rck: + lwz r3, 0 (sp) + lwz r4, 4 (sp) + addi sp, sp, 4 ! leave value on stack + + lwz r5, 0 (r3) + cmpw r4, r5 + blt .trap_erange + + lwz r5, 4 (r3) + cmpw r4, r5 + bgt .trap_erange + + blr diff --git a/mach/powerpc/libem/ret.s b/mach/powerpc/libem/ret.s index cca79ae86..c498af240 100644 --- a/mach/powerpc/libem/ret.s +++ b/mach/powerpc/libem/ret.s @@ -1,19 +1,12 @@ -# -! $Source$ -! $State$ -! $Revision$ - -#include "powerpc.h" - .sect .text - + ! Standard boilerplate for returning from functions. .define .ret .ret: lwz r0, 4(fp) mtspr lr, r0 - lwz r0, 0(fp) ! our stack frame becomes invalid as soon as... - addi sp, fp, 8 ! ...we change sp - or fp, r0, r0 - bclr ALWAYS, 0, 0 + lwz r0, 0(fp) ! our stack frame becomes invalid as soon as... + addi sp, fp, 8 ! ...we change sp + mr fp, r0 + blr diff --git a/mach/powerpc/libem/sar4.s b/mach/powerpc/libem/sar4.s index 0c1368af1..7c9778958 100644 --- a/mach/powerpc/libem/sar4.s +++ b/mach/powerpc/libem/sar4.s @@ -1,6 +1,3 @@ -# -#include "powerpc.h" - .sect .text ! Store to bounds-checked array. @@ -18,21 +15,21 @@ ! r3 = ptr to element ! r0 = size of element - cmpi cr0, 0, r0, 1 - bc IFFALSE, EQ, 1f + cmpwi r0, 1 + bne 1f ! Store 1 byte. lwz r4, 0(sp) addi sp, sp, 4 stb r4, 0(r3) - bclr ALWAYS, 0, 0 + blr 1: - cmpi cr0, 0, r0, 2 - bc IFFALSE, EQ, 2f + cmpwi r0, 2 + bne 2f ! Store 2 bytes. lwz r4, 0(sp) addi sp, sp, 4 sth r4, 0(r3) - bclr ALWAYS, 0, 0 + blr 2: ! Store r0 bytes, where r0 must be a positive multiple of 4. or r5, r0, r0 ! index r5 = length r0 @@ -40,6 +37,6 @@ addic. r5, r5, -4 ! r5 -= 4 lwzx r4, r5, sp stwx r4, r5, r3 - bc IFTRUE, GT, 3b ! loop if r5 > 0 + bgt 3b ! loop if r5 > 0 add sp, r0, sp ! move stack pointer up - bclr ALWAYS, 0, 0 + blr diff --git a/mach/powerpc/libem/set.s b/mach/powerpc/libem/set.s new file mode 100644 index 000000000..3c4a9e579 --- /dev/null +++ b/mach/powerpc/libem/set.s @@ -0,0 +1,30 @@ +.sect .text + +! Create singleton set. +! Stack: ( bitnumber size -- set ) + +.define .set +.set: + lwz r3, 0 (sp) + lwz r4, 4 (sp) + addi sp, sp, 8 + + srwi r7, r3, 2 + neg r5, r3 + add sp, sp, r5 ! allocate set + mr r6, sp ! r6 = ptr to set + mtspr ctr, r7 ! ctr = r3 / 4 +1: + clrrwi. r7, r4, 5 ! r7 = r4 & ~31 + beq 2f ! branch if r4 in 0..31 + li r5, 0 ! no bit, word is zero + b 3f +2: + li r5, 1 + slw r5, r5, r4 ! yes bit, set bit in word +3: + stw r5, 0(r6) ! store word in set + addi r4, r4, -32 + addi r6, r6, 4 + bdnz 1b ! loop ctr times + blr diff --git a/mach/powerpc/libem/sts.s b/mach/powerpc/libem/sts.s index 2f8022ad9..411b0fb66 100644 --- a/mach/powerpc/libem/sts.s +++ b/mach/powerpc/libem/sts.s @@ -1,10 +1,3 @@ -# -! $Source$ -! $State$ -! $Revision$ - -#include "powerpc.h" - .sect .text ! Stores a variable-sized structure from the stack. @@ -15,35 +8,35 @@ .define .sts .sts: ! These sizes are handled specially. - + lwz r5, 0(sp) - cmpi cr0, 0, r3, 1 - bc IFFALSE, GT, size1 - - cmpi cr0, 0, r3, 2 - bc IFFALSE, GT, size2 - - cmpi cr0, 0, r3, 4 - bc IFFALSE, GT, size4 - + cmplwi r3, 1 + ble size1 + + cmplwi r3, 2 + ble size2 + + cmplwi r3, 4 + ble size4 + ! Variable-sized structure. - + addi r3, r3, 3 - andi. r3, r3, ~3 ! align size - - srawi r3, r3, 2 ! convert size to the number of words + clrrwi r3, r3, 2 ! align size + + srwi r3, r3, 2 ! convert size to the number of words mtspr ctr, r3 - + 1: lwz r5, 0(sp) addi sp, sp, 4 stw r5, 0(r4) addi r4, r4, 4 - bc DNZ, 0, 1b ! decrement CTR, jump if non-zero - bclr ALWAYS, 0, 0 - + bdnz 1b ! decrement CTR, jump if non-zero + blr + size1: stb r5, 0(r4) b 1f @@ -54,4 +47,4 @@ size4: stw r5, 0(r4) 1: addi sp, sp, 4 - bclr ALWAYS, 0, 0 + blr diff --git a/mach/powerpc/libem/tge.s b/mach/powerpc/libem/tge.s deleted file mode 100644 index 4740d8436..000000000 --- a/mach/powerpc/libem/tge.s +++ /dev/null @@ -1,46 +0,0 @@ -# -! $Source$ -! $State$ -! $Revision$ - -#include "powerpc.h" - -.sect .rom - -! Lookup table for tge. - -.define .teq_table -.teq_table: - .data4 1 ! . . - .data4 0 ! . G - .data4 0 ! L . - -.define .tne_table -.tne_table: - .data4 0 ! . . - .data4 1 ! . G - .data4 1 ! L . - -.define .tgt_table -.tgt_table: - .data4 0 ! . . - .data4 1 ! . G - .data4 0 ! L . - -.define .tge_table -.tge_table: - .data4 1 ! . . - .data4 1 ! . G - .data4 0 ! L . - -.define .tlt_table -.tlt_table: - .data4 0 ! . . - .data4 0 ! . G - .data4 1 ! L . - -.define .tle_table -.tle_table: - .data4 1 ! . . - .data4 0 ! . G - .data4 1 ! L . diff --git a/mach/powerpc/libem/xor.s b/mach/powerpc/libem/xor.s new file mode 100644 index 000000000..acb02a032 --- /dev/null +++ b/mach/powerpc/libem/xor.s @@ -0,0 +1,22 @@ +.sect .text + +! Set symmetric difference. +! Stack: ( b a -- a/b ) +! With r3 = size of set + +.define .xor +.xor: + mr r4, sp ! r4 = ptr to set a + add r5, sp, r3 ! r5 = ptr to set b + srwi r6, r3, 2 + mtspr ctr, r6 ! ctr = r3 / 4 +1: + lwz r7, 0(r4) + lwz r8, 0(r5) + xor r8, r7, r8 ! symmetric difference of words + stw r8, 0(r5) + addi r4, r4, 4 + addi r5, r5, 4 + bdnz 1b ! loop ctr times + add sp, sp, r3 + blr diff --git a/mach/powerpc/libem/zer.s b/mach/powerpc/libem/zer.s new file mode 100644 index 000000000..a47a150cc --- /dev/null +++ b/mach/powerpc/libem/zer.s @@ -0,0 +1,21 @@ +.sect .text + +! Create empty set. +! Stack: ( size -- set ) + +.define .zer +.zer: + lwz r3, 0(sp) + addi sp, sp, 4 + + srwi r7, r3, 2 + li r4, 0 ! r4 = zero + neg r5, r3 + add sp, sp, r5 ! allocate set + mr r6, sp ! r6 = ptr to set + mtspr ctr, r7 ! ctr = r3 / 4 +1: + stw r4, 0(r6) ! store zero in set + addi r6, r6, 4 + bdnz 1b ! loop ctr times + blr diff --git a/mach/powerpc/mcg/table b/mach/powerpc/mcg/table index 8511dbb5b..b72990c36 100644 --- a/mach/powerpc/mcg/table +++ b/mach/powerpc/mcg/table @@ -572,26 +572,26 @@ PATTERNS out:(int)reg = IFEQ.I(in:(cr)cr) emit "mfcr %out" /* get cr0 */ - emit "rlwinm %out, %out, [32-2], 2, 31" /* extract just EQ */ + emit "rlwinm %out, %out, 3, 31, 31" /* extract just EQ */ cost 8; +#if 0 out:(int)reg = IFEQ.I(in:(int)reg) emit "cntlzw %out, %in" /* returns 0..32 */ - emit "rlwinm %out, %out, [32-5], 5, 31" /* if 32, return 1, otherwise 0 */ + emit "rlwinm %out, %out, [32-5], 31, 31" /* if 32, return 1, otherwise 0 */ cost 8; +#endif out:(int)reg = IFLT.I(in:(cr)cr) emit "mfcr %out" /* get cr0 */ - emit "andi. %out, %out, 1" /* leave just LT */ + emit "rlwinm %out, %out, 1, 31, 31" /* leave just LT */ cost 8; out:(int)reg = IFLE.I(in:(cr)cr) emit "mfcr %out" /* get cr0 */ - emit "andi. %out, %out, 5" /* leave just LT and EQ */ - emit "cntlzw %out, %out" /* returns 0..32 */ - emit "rlwinm %out, %out, [32-5], 5, 31" /* if 32, return 1, otherwise 0 */ + emit "rlwinm %out, %out, 2, 31, 31" /* leave just GT */ emit "xori %out, %out, 1" /* negate */ - cost 8; + cost 12; @@ -673,10 +673,9 @@ PATTERNS emit "neg %out, %left" cost 4; - out:(int)reg = NOT.I(left:(int)reg) - emit "cntlzw %out, %left" - emit "rlwinm %out, %out, 32-5, 5, 31" - cost 8; + out:(int)reg = NOT.I(in:(int)reg) + emit "nor %out, %in, %in" + cost 4; ALUR(AND.I, "and") ALUCC(AND.I, "andi.") diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index 77fdaedf1..24822482c 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -10,7 +10,7 @@ INT64 = 8 FP_OFFSET = 0 /* Offset of saved FP relative to our FP */ PC_OFFSET = 4 /* Offset of saved PC relative to our FP */ -#define COMMENT(n) /* noop */ +#define COMMENT(n) /* comment {LABEL, n} */ #define nicesize(x) ((x)==INT8 || (x)==INT16 || (x)==INT32 || (x)==INT64) @@ -27,44 +27,33 @@ PC_OFFSET = 4 /* Offset of saved PC relative to our FP */ #define los(n) (lo(n) | (((0-(lo(n)>>15)) & ~0xFFFF))) #define his(n) ((hi(n) + (lo(n)>>15)) & 0xFFFF) -#define IFFALSE {CONST, 4} -#define IFTRUE {CONST, 12} -#define ALWAYS {CONST, 20} -#define DCTRZ {CONST, 34} - -#define LT {CONST, 0} -#define GT {CONST, 1} -#define EQ {CONST, 2} - - PROPERTIES GPR /* any GPR */ REG /* any allocatable GPR */ - REG_PAIR /* speed hack for sti 8 */ - FPR /* any FPR */ - FREG /* any allocatable FPR */ + REG_PAIR(8) /* speed hack for sti 8 */ + FPR(8) /* any FPR */ + FREG(8) /* any allocatable FPR */ FSREG /* any allocatable single-precision FPR */ SPR /* any SPR */ CR /* any CR */ - + GPR0 GPRSP GPRFP GPR3 GPR4 GPR5 GPR6 GPR7 GPR8 GPR9 GPR10 GPR11 GPR12 GPR13 GPR14 GPR15 GPR16 GPR17 GPR18 GPR19 GPR20 GPR21 GPR22 GPR23 GPR24 GPR25 GPR26 GPR27 GPR28 GPR29 GPR30 GPR31 - - CR0 CR1 - FPR0 FPR1 FPR2 FPR3 FPR4 FPR5 FPR6 FPR7 - FPR8 FPR9 FPR10 FPR11 FPR12 FPR13 FPR14 FPR15 - FPR16 FPR17 FPR18 FPR19 FPR20 FPR21 FPR22 FPR23 - FPR24 FPR25 FPR26 FPR27 FPR28 FPR29 FPR30 FPR31 + FPR0(8) FPR1(8) FPR2(8) FPR3(8) FPR4(8) FPR5(8) FPR6(8) FPR7(8) + FPR8(8) FPR9(8) FPR10(8) FPR11(8) FPR12(8) FPR13(8) FPR14(8) FPR15(8) + FPR16(8) FPR17(8) FPR18(8) FPR19(8) FPR20(8) FPR21(8) FPR22(8) FPR23(8) + FPR24(8) FPR25(8) FPR26(8) FPR27(8) FPR28(8) FPR29(8) FPR30(8) FPR31(8) + REGISTERS /* Reverse order to encourage ncg to allocate them from r31 down */ - + R31("r31") : GPR, REG, GPR31 regvar. R30("r30") : GPR, REG, GPR30 regvar. R29("r29") : GPR, REG, GPR29 regvar. @@ -85,7 +74,7 @@ REGISTERS R14("r14") : GPR, REG, GPR14 regvar. R13("r13") : GPR, REG, GPR13 regvar. R12("r12") : GPR, REG, GPR12. - R11("r11") : GPR, GPR11. + R11("r11") : GPR, REG, GPR11. R10("r10") : GPR, REG, GPR10. R9("r9") : GPR, REG, GPR9. R8("r8") : GPR, REG, GPR8. @@ -158,23 +147,22 @@ REGISTERS LR("lr") : SPR. CTR("ctr") : SPR. - C0("cr0") : CR, CR0. + CR0("cr0") : CR. -#define RSCRATCH R11 +#define RSCRATCH R0 #define FSCRATCH F0 TOKENS -/* Used only in instruction descriptions (to generate the correct syntax). */ - - GPRINDIRECT = { GPR reg; INT off; } 4 off "(" reg ")". - CONST = { INT val; } 4 val. - /* Primitives */ + CONST = { INT val; } 4 val. LABEL = { ADDR adr; } 4 adr. - LOCAL = { INT off; } 4. + LABEL_HI = { ADDR adr; } 4 "hi16[" adr "]". + LABEL_HA = { ADDR adr; } 4 "ha16[" adr "]". + LABEL_LO = { ADDR adr; } 4 "lo16[" adr "]". + LOCAL = { INT off; } 4 ">>> BUG IN LOCAL". /* Allows us to use regvar() to refer to registers */ @@ -192,33 +180,32 @@ TOKENS /* Expression partial results */ - SUM_RIS = { GPR reg; INT offhi; } 4. - SUM_RC = { GPR reg; INT off; } 4. - SUM_RR = { GPR reg1; GPR reg2; } 4. - - TRISTATE_RC_S = { GPR reg; INT val; } 4. - TRISTATE_RC_U = { GPR reg; INT val; } 4. - TRISTATE_RR_S = { GPR reg1; GPR reg2; } 4. - TRISTATE_RR_U = { GPR reg1; GPR reg2; } 4. - - TRISTATE_FF = { FPR reg1; FPR reg2; } 4. - + SUM_RIS = { GPR reg; INT offhi; } 4. /* reg + (offhi << 16) */ + SUM_RC = { GPR reg; INT off; } 4. /* reg + off */ + SUM_RL = { GPR reg; ADDR adr; } 4. /* reg + lo16[adr] */ + SUM_RR = { GPR reg1; GPR reg2; } 4. /* reg1 + reg2 */ + SEX_B = { GPR reg; } 4. SEX_H = { GPR reg; } 4. - - IND_RC_B = { GPR reg; INT off; } 4. - IND_RR_B = { GPR reg1; GPR reg2; } 4. - IND_RC_H = { GPR reg; INT off; } 4. - IND_RR_H = { GPR reg1; GPR reg2; } 4. - IND_RC_H_S = { GPR reg; INT off; } 4. - IND_RR_H_S = { GPR reg1; GPR reg2; } 4. - IND_RC_W = { GPR reg; INT off; } 4. - IND_RR_W = { GPR reg1; GPR reg2; } 4. - IND_RC_D = { GPR reg; INT off; } 8. - IND_RR_D = { GPR reg1; GPR reg2; } 8. - + + IND_RC_B = { GPR reg; INT off; } 4 off "(" reg ")". + IND_RL_B = { GPR reg; ADDR adr; } 4 "lo16[" adr "](" reg ")". + IND_RR_B = { GPR reg1; GPR reg2; } 4. + IND_RC_H = { GPR reg; INT off; } 4 off "(" reg ")". + IND_RL_H = { GPR reg; ADDR adr; } 4 "lo16[" adr "](" reg ")". + IND_RR_H = { GPR reg1; GPR reg2; } 4. + IND_RC_H_S = { GPR reg; INT off; } 4 off "(" reg ")". + IND_RL_H_S = { GPR reg; ADDR adr; } 4 "lo16[" adr "](" reg ")". + IND_RR_H_S = { GPR reg1; GPR reg2; } 4. + IND_RC_W = { GPR reg; INT off; } 4 off "(" reg ")". + IND_RL_W = { GPR reg; ADDR adr; } 4 "lo16[" adr "](" reg ")". + IND_RR_W = { GPR reg1; GPR reg2; } 4. + IND_RC_D = { GPR reg; INT off; } 8 off "(" reg ")". + IND_RL_D = { GPR reg; ADDR adr; } 8 "lo16[" adr "](" reg ")". + IND_RR_D = { GPR reg1; GPR reg2; } 8. + NOT_R = { GPR reg; } 4. - + AND_RR = { GPR reg1; GPR reg2; } 4. OR_RR = { GPR reg1; GPR reg2; } 4. OR_RIS = { GPR reg; INT valhi; } 4. @@ -227,6 +214,20 @@ TOKENS XOR_RIS = { GPR reg; INT valhi; } 4. XOR_RC = { GPR reg; INT val; } 4. + COND_RC = { GPR reg; INT val; } 4. + COND_RR = { GPR reg1; GPR reg2; } 4. + CONDL_RC = { GPR reg; INT val; } 4. + CONDL_RR = { GPR reg1; GPR reg2; } 4. + COND_FS = { FSREG reg1; FSREG reg2; } 4. + COND_FD = { FREG reg1; FREG reg2; } 4. + + XEQ = { GPR reg; } 4. + XNE = { GPR reg; } 4. + XGT = { GPR reg; } 4. + XGE = { GPR reg; } 4. + XLT = { GPR reg; } 4. + XLE = { GPR reg; } 4. + SETS @@ -237,32 +238,29 @@ SETS /* unsigned 16-bit integer */ UCONST2 = CONST_0000_7FFF + CONST_8000 + CONST_8001_FFFF. /* any constant on stack */ - CONST_ALL = CONST_N8000 + CONST_N7FFF_N0001 + CONST_0000_7FFF + + CONST_STACK = CONST_N8000 + CONST_N7FFF_N0001 + CONST_0000_7FFF + CONST_8000 + CONST_8001_FFFF + CONST_HZ + CONST_HL. - SUM_ALL = SUM_RC + SUM_RR. - - TRISTATE_ALL = TRISTATE_RC_S + TRISTATE_RC_U + TRISTATE_RR_S + - TRISTATE_RR_U + TRISTATE_FF. - + SUM_ALL = SUM_RC + SUM_RL + SUM_RR. + SEX_ALL = SEX_B + SEX_H. - + LOGICAL_ALL = NOT_R + AND_RR + OR_RR + OR_RC + XOR_RR + XOR_RC. - /* indirect 4-byte value */ - IND_ALL_W = IND_RC_W + IND_RR_W. - /* indirect 8-byte value */ - IND_ALL_D = IND_RC_D + IND_RR_D. - /* any indirect value that fits in a GPR */ - IND_ALL_BHW = IND_RC_B + IND_RR_B + IND_RC_H + IND_RR_H + - IND_RC_H_S + IND_RR_H_S + IND_ALL_W. + IND_ALL_B = IND_RC_B + IND_RL_B + IND_RR_B. + IND_ALL_H = IND_RC_H + IND_RL_H + IND_RR_H + + IND_RC_H_S + IND_RL_H_S + IND_RR_H_S. + IND_ALL_W = IND_RC_W + IND_RL_W + IND_RR_W. + IND_ALL_D = IND_RC_D + IND_RL_D + IND_RR_D. + IND_ALL_BHW = IND_ALL_B + IND_ALL_H + IND_ALL_W. /* anything killed by sti (store indirect) */ MEMORY = IND_ALL_BHW + IND_ALL_D. - OP_ALL_W = SUM_ALL + TRISTATE_ALL + SEX_ALL + LOGICAL_ALL + - IND_ALL_W. + /* any stack token that we can easily move to GPR */ + ANY_BHW = REG + CONST_STACK + SEX_ALL + + SUM_ALL + IND_ALL_BHW + LOGICAL_ALL. INSTRUCTIONS @@ -281,22 +279,37 @@ INSTRUCTIONS add GPR:wo, GPR:ro, GPR:ro. addX "add." GPR:wo, GPR:ro, GPR:ro. - addi GPR:wo, GPR:ro, CONST:ro. - addis GPR:wo, GPR:ro, CONST:ro. + addi GPR:wo, GPR:ro, CONST+LABEL_LO:ro. + li GPR:wo, CONST:ro. + addis GPR:wo, GPR:ro, CONST+LABEL_HI+LABEL_HA:ro. + lis GPR:wo, CONST+LABEL_HI+LABEL_HA:ro. and GPR:wo, GPR:ro, GPR:ro. andc GPR:wo, GPR:ro, GPR:ro. andiX "andi." GPR:wo:cc, GPR:ro, CONST:ro. andisX "andis." GPR:wo:cc, GPR:ro, CONST:ro. b LABEL:ro. bc CONST:ro, CONST:ro, LABEL:ro. + beq LABEL:ro. + bne LABEL:ro. + bgt LABEL:ro. + bge LABEL:ro. + blt LABEL:ro. + ble LABEL:ro. + bxx LABEL:ro. /* dummy */ bcctr CONST:ro, CONST:ro, CONST:ro. + bctr. bcctrl CONST:ro, CONST:ro, CONST:ro. + bctrl. bclr CONST:ro, CONST:ro, CONST:ro. bl LABEL:ro. cmp CR:ro, CONST:ro, GPR:ro, GPR:ro kills :cc. + cmpw GPR:ro, GPR:ro kills :cc. cmpi CR:ro, CONST:ro, GPR:ro, CONST:ro kills :cc. + cmpwi GPR:ro, CONST:ro kills :cc. cmpl CR:ro, CONST:ro, GPR:ro, GPR:ro kills :cc. + cmplw GPR:ro, GPR:ro kills :cc. cmpli CR:ro, CONST:ro, GPR:ro, CONST:ro kills :cc. + cmplwi GPR:ro, CONST:ro kills :cc. divw GPR:wo, GPR:ro, GPR:ro cost(4, 23). divwu GPR:wo, GPR:ro, GPR:ro cost(4, 23). eqv GPR:wo, GPR:ro, GPR:ro. @@ -304,7 +317,8 @@ INSTRUCTIONS extsh GPR:wo, GPR:ro. fadd FREG:wo, FREG:ro, FREG:ro cost(4, 5). fadds FSREG:wo, FSREG:ro, FSREG:ro cost(4, 5). - fcmpo CR:wo, FPR:ro, FPR:ro cost(4, 5). + fcmpo CR:wo, FREG:ro, FREG:ro cost(4, 5). + fcmpo CR:wo, FSREG:ro, FSREG:ro cost(4, 5). fdiv FREG:wo, FREG:ro, FREG:ro cost(4, 35). fdivs FSREG:wo, FSREG:ro, FSREG:ro cost(4, 21). fmr FPR:wo, FPR:ro cost(4, 5). @@ -316,23 +330,21 @@ INSTRUCTIONS frsp FSREG:wo, FREG:ro cost(4, 5). fsub FREG:wo, FREG:ro, FREG:ro cost(4, 5). fsubs FSREG:wo, FSREG:ro, FSREG:ro cost(4, 5). - lbz GPR:wo, GPRINDIRECT:ro cost(4, 3). + lbz GPR:wo, IND_RC_B+IND_RL_B:ro cost(4, 3). lbzx GPR:wo, GPR:ro, GPR:ro cost(4, 3). - lfd FPR:wo, GPRINDIRECT:ro cost(4, 5). - lfdu FPR:wo, GPRINDIRECT:ro cost(4, 5). + lfd FPR:wo, IND_RC_D+IND_RL_D:ro cost(4, 5). + lfdu FPR:wo, IND_RC_D:ro cost(4, 5). lfdx FPR:wo, GPR:ro, GPR:ro cost(4, 5). - lfs FSREG:wo, GPRINDIRECT:ro cost(4, 4). - lfsu FSREG:wo, GPRINDIRECT:rw cost(4, 4). + lfs FSREG:wo, IND_RC_W+IND_RL_W:ro cost(4, 4). + lfsu FSREG:wo, IND_RC_W:rw cost(4, 4). lfsx FSREG:wo, GPR:ro, GPR:ro cost(4, 4). - lha GPR:wo, GPRINDIRECT:ro cost(4, 3). + lha GPR:wo, IND_RC_H_S+IND_RL_H_S:ro cost(4, 3). lhax GPR:wo, GPR:ro, GPR:ro cost(4, 3). - lhz GPR:wo, GPRINDIRECT:ro cost(4, 3). + lhz GPR:wo, IND_RC_H+IND_RL_H:ro cost(4, 3). lhzx GPR:wo, GPR:ro, GPR:ro cost(4, 3). - li32 GPR:wo, CONST:ro cost(8, 2). - li32 GPR:wo, LABEL:ro cost(8, 2). - lwzu GPR:wo, GPRINDIRECT:ro cost(4, 3). + lwzu GPR:wo, IND_RC_W:ro cost(4, 3). lwzx GPR:wo, GPR:ro, GPR:ro cost(4, 3). - lwz GPR:wo, GPRINDIRECT:ro cost(4, 3). + lwz GPR:wo, IND_RC_W+IND_RL_W:ro cost(4, 3). nand GPR:wo, GPR:ro, GPR:ro. neg GPR:wo, GPR:ro. nor GPR:wo, GPR:ro, GPR:ro. @@ -341,63 +353,61 @@ INSTRUCTIONS mfspr GPR:wo, SPR:ro cost(4, 3). mtspr SPR:wo, GPR:ro cost(4, 2). or GPR:wo, GPR:ro, GPR:ro. - orc GPR:wo, GPR:ro, GPR:ro. - ori GPR:wo, GPR:ro, CONST:ro. - oris GPR:wo, GPR:ro, CONST:ro. + mr GPR:wo, GPR:ro. orX "or." GPR:wo:cc, GPR:ro, GPR:ro. + orX_readonly "or." GPR:ro:cc, GPR:ro, GPR:ro. + orc GPR:wo, GPR:ro, GPR:ro. + ori GPR:wo, GPR:ro, CONST+LABEL_LO:ro. + oris GPR:wo, GPR:ro, CONST:ro. rlwinm GPR:wo, GPR:ro, CONST:ro, CONST:ro, CONST:ro. + extlwi GPR:wo, GPR:ro, CONST:ro, CONST:ro. + extrwi GPR:wo, GPR:ro, CONST:ro, CONST:ro. slw GPR:wo, GPR:ro, GPR:ro. subf GPR:wo, GPR:ro, GPR:ro. sraw GPR:wo, GPR:ro, GPR:ro cost(4, 2). srawi GPR:wo, GPR:ro, CONST:ro cost(4, 2). srw GPR:wo, GPR:ro, GPR:ro. - stb GPR:ro, GPRINDIRECT:rw cost(4, 3). + stb GPR:ro, IND_RC_B+IND_RL_B:rw cost(4, 3). stbx GPR:ro, GPR:ro, GPR:ro cost(4, 3). - stfd FPR:ro, GPRINDIRECT:rw cost(4, 4). - stfdu FPR:ro, GPRINDIRECT:rw cost(4, 4). + stfd FPR:ro, IND_RC_D+IND_RL_D:rw cost(4, 4). + stfdu FPR:ro, IND_RC_D:rw cost(4, 4). stfdx FPR:ro, GPR:ro, GPR:ro cost(4, 4). - stfs FSREG:ro, GPRINDIRECT:rw cost(4, 3). - stfsu FSREG:ro, GPRINDIRECT:rw cost(4, 3). + stfs FSREG:ro, IND_RC_W+IND_RL_W:rw cost(4, 3). + stfsu FSREG:ro, IND_RC_W:rw cost(4, 3). stfsx FSREG:ro, GPR:ro, GPR:ro cost(4, 3). - sth GPR:ro, GPRINDIRECT:rw cost(4, 3). + sth GPR:ro, IND_RC_H+IND_RL_H:rw cost(4, 3). sthx GPR:ro, GPR:ro, GPR:ro cost(4, 3). - stw GPR:ro, GPRINDIRECT:rw cost(4, 3). + stw GPR:ro, IND_RC_W+IND_RL_W:rw cost(4, 3). stwx GPR:ro, GPR:ro, GPR:ro cost(4, 3). - stwu GPR+GPRE:ro, GPRINDIRECT:rw cost(4, 3). + stwu GPR+LOCAL:ro, IND_RC_W:rw cost(4, 3). xor GPR:wo, GPR:ro, GPR:ro. xori GPR:wo, GPR:ro, CONST:ro. xoris GPR:wo, GPR:ro, CONST:ro. - comment "!" LABEL:ro cost(0, 0). + comment "!" LABEL:ro cost(0, 0). - MOVES from GPR to GPR - gen - COMMENT("move GPR->GPR") - or %2, %1, %1 + gen mr %2, %1 -/* GPRE exists solely to allow us to use regvar() (which can only be used in - an expression) as a register constant. */ - - from GPR to GPRE - gen - COMMENT("move GPR->GPRE") - or %2.reg, %1, %1 - /* Constants */ - from CONST_ALL smalls(%val) to GPR + from CONST + CONST_STACK smalls(%val) to GPR gen - COMMENT("move CONST_ALL->GPR smalls") - addi %2, R0, {CONST, %1.val} + COMMENT("move CONST->GPR smalls") + li %2, {CONST, %1.val} - from CONST_ALL + CONST to GPR + from CONST + CONST_STACK lo(%val)==0 to GPR gen - COMMENT("move CONST_ALL->GPR") - addis %2, R0, {CONST, hi(%1.val)} + COMMENT("move CONST->GPR shifted") + lis %2, {CONST, hi(%1.val)} + + from CONST + CONST_STACK to GPR + gen + COMMENT("move CONST->GPR") + lis %2, {CONST, hi(%1.val)} ori %2, %2, {CONST, lo(%1.val)} /* Can't use addi %2, %2, {CONST, los(%1.val)} * because %2 might be R0. */ @@ -405,279 +415,225 @@ MOVES from LABEL to GPR gen COMMENT("move LABEL->GPR") - li32 %2, {LABEL, %1.adr} - + lis %2, {LABEL_HI, %1.adr} + ori %2, %2, {LABEL_LO, %1.adr} + + from LABEL_HA to GPR + gen lis %2, %1 + /* Sign extension */ from SEX_B to GPR - gen - COMMENT("move SEX_B->GPR") - extsb %2, %1.reg - + gen extsb %2, %1.reg + from SEX_H to GPR - gen - COMMENT("move SEX_H->GPR") - extsh %2, %1.reg - + gen extsh %2, %1.reg + /* Register + something */ from SUM_RIS to GPR - gen - COMMENT("move SUM_RIS->GPR") - addis %2, %1.reg, {CONST, %1.offhi} + gen addis %2, %1.reg, {CONST, %1.offhi} from SUM_RC to GPR - gen - COMMENT("move SUM_RC->GPR") - addi %2, %1.reg, {CONST, %1.off} + gen addi %2, %1.reg, {CONST, %1.off} + + from SUM_RL to GPR + gen addi %2, %1.reg, {LABEL_LO, %1.adr} from SUM_RR to GPR - gen - COMMENT("move SUM_RR->GPR") - add %2, %1.reg1, %1.reg2 + gen add %2, %1.reg1, %1.reg2 /* Read byte */ - from IND_RC_B to GPR - gen - COMMENT("move IND_RC_B->GPR") - lbz %2, {GPRINDIRECT, %1.reg, %1.off} + from IND_RC_B+IND_RL_B to GPR + gen lbz %2, %1 from IND_RR_B to GPR - gen - COMMENT("move IND_RR_B->GPR") - lbzx %2, %1.reg1, %1.reg2 + gen lbzx %2, %1.reg1, %1.reg2 /* Write byte */ - from GPR to IND_RC_B - gen - COMMENT("move GPR->IND_RC_B") - stb %1, {GPRINDIRECT, %2.reg, %2.off} + from GPR to IND_RC_B+IND_RL_B + gen stb %1, %2 from GPR to IND_RR_B - gen - COMMENT("move GPR->IND_RR_B") - stbx %1, %2.reg1, %2.reg2 + gen stbx %1, %2.reg1, %2.reg2 /* Read halfword (short) */ - from IND_RC_H to GPR - gen - COMMENT("move IND_RC_H->GPR") - lhz %2, {GPRINDIRECT, %1.reg, %1.off} + from IND_RC_H+IND_RL_H to GPR + gen lhz %2, %1 from IND_RR_H to GPR - gen - COMMENT("move IND_RR_H->GPR") - lhzx %2, %1.reg1, %1.reg2 + gen lhzx %2, %1.reg1, %1.reg2 - from IND_RC_H_S to GPR - gen - COMMENT("move IND_RC_H_S->GPR") - lha %2, {GPRINDIRECT, %1.reg, %1.off} + from IND_RC_H_S+IND_RL_H_S to GPR + gen lha %2, %1 from IND_RR_H_S to GPR - gen - COMMENT("move IND_RR_H_S->GPR") - lhax %2, %1.reg1, %1.reg2 + gen lhax %2, %1.reg1, %1.reg2 /* Write halfword */ - from GPR to IND_RC_H - gen - COMMENT("move GPR->IND_RC_H") - sth %1, {GPRINDIRECT, %2.reg, %2.off} + from GPR to IND_RC_H+IND_RL_H + gen sth %1, %2 from GPR to IND_RR_H - gen - COMMENT("move GPR->IND_RR_H") - sthx %1, %2.reg1, %2.reg2 + gen sthx %1, %2.reg1, %2.reg2 /* Read word */ - from IND_RC_W to GPR - gen - COMMENT("move IND_RC_W->GPR") - lwz %2, {GPRINDIRECT, %1.reg, %1.off} + from IND_RC_W+IND_RL_W to GPR + gen lwz %2, %1 from IND_RR_W to GPR - gen - COMMENT("move IND_RR_W->GPR") - lwzx %2, %1.reg1, %1.reg2 + gen lwzx %2, %1.reg1, %1.reg2 - from IND_RC_W to FSREG - gen - COMMENT("move IND_RC_W->FSREG") - lfs %2, {GPRINDIRECT, %1.reg, %1.off} + from IND_RC_W+IND_RL_W to FSREG + gen lfs %2, %1 from IND_RR_W to FSREG - gen - COMMENT("move IND_RR_W->FSREG") - lfsx %2, %1.reg1, %1.reg2 + gen lfsx %2, %1.reg1, %1.reg2 /* Write word */ - from GPR to IND_RC_W - gen - COMMENT("move GPR->IND_RC_W") - stw %1, {GPRINDIRECT, %2.reg, %2.off} + from GPR to IND_RC_W+IND_RL_W + gen stw %1, %2 from GPR to IND_RR_W - gen - COMMENT("move GPR->IND_RR_W") - stwx %1, %2.reg1, %2.reg2 + gen stwx %1, %2.reg1, %2.reg2 - from FSREG to IND_RC_W - gen - COMMENT("move FSREG->IND_RC_W") - stfs %1, {GPRINDIRECT, %2.reg, %2.off} + from FSREG to IND_RC_W+IND_RL_W + gen stfs %1, %2 from FSREG to IND_RR_W - gen - COMMENT("move FSREG->IND_RR_W") - stfsx %1, %2.reg1, %2.reg2 + gen stfsx %1, %2.reg1, %2.reg2 /* Read double */ - from IND_RC_D to FPR - gen - COMMENT("move IND_RC_D->FPR") - lfd %2, {GPRINDIRECT, %1.reg, %1.off} + from IND_RC_D+IND_RL_D to FPR + gen lfd %2, %1 from IND_RR_D to FPR - gen - COMMENT("move IND_RR_D->FPR") - lfdx %2, %1.reg1, %1.reg2 + gen lfdx %2, %1.reg1, %1.reg2 /* Write double */ - from FPR to IND_RC_D - gen - COMMENT("move FPR->IND_RC_D") - stfd %1, {GPRINDIRECT, %2.reg, %2.off} + from FPR to IND_RC_D+IND_RL_D + gen stfd %1, %2 from FPR to IND_RR_D - gen - COMMENT("move FPR->IND_RR_W") - stfdx %1, %2.reg1, %2.reg2 - -/* Extract condition code field (actually produces (CC&3)<<2) */ - - from CR0 to GPR - gen - COMMENT("move CR0->GPR") - mfcr %2 - rlwinm %2, %2, {CONST, 4}, {CONST, 32-4}, {CONST, 31-2} - -/* Comparisons */ - - from TRISTATE_RR_S to CR0 - gen - cmp %2, {CONST, 0}, %1.reg1, %1.reg2 - - from TRISTATE_RR_U to CR0 - gen - cmpl %2, {CONST, 0}, %1.reg1, %1.reg2 - - from TRISTATE_RC_S to CR0 - gen - COMMENT("move TRISTATE_RC_S->CR0 large") - move {CONST, %1.val}, RSCRATCH - cmp %2, {CONST, 0}, %1.reg, RSCRATCH - - from TRISTATE_RC_U smallu(%val) to CR0 - gen - COMMENT("move TRISTATE_RC_U->CR0 small") - cmpli %2, {CONST, 0}, %1.reg, {CONST, %1.val} - - from TRISTATE_RC_U to CR0 - gen - COMMENT("move TRISTATE_RC_U->CR0") - move {CONST, %1.val}, RSCRATCH - cmpl %2, {CONST, 0}, %1.reg, RSCRATCH - - from TRISTATE_FF to CR0 - gen - COMMENT("move TRISTATE_FF->CR0") - fcmpo %2, %1.reg1, %1.reg2 - - from GPR to CR0 - gen - COMMENT("move GPR->CR0") - orX RSCRATCH, %1, %1 /* alas, can't call test */ - - from TRISTATE_RR_S + TRISTATE_RC_S + TRISTATE_FF to GPR - gen - COMMENT("move TRISTATE_R*_S->GPR") - move %1, C0 - move C0, RSCRATCH - move {LABEL, ".tristate_s_table"}, %2 - lwzx %2, %2, RSCRATCH - - from TRISTATE_RR_U + TRISTATE_RC_U to GPR - gen - COMMENT("move TRISTATE_R*_U->GPR") - move %1, C0 - move C0, RSCRATCH - move {LABEL, ".tristate_u_table"}, %2 - lwzx %2, %2, RSCRATCH + gen stfdx %1, %2.reg1, %2.reg2 /* Logicals */ from NOT_R to GPR - gen - COMMENT("move NOT_R->GPR") - nor %2, %1.reg, %1.reg + gen nor %2, %1.reg, %1.reg from AND_RR to GPR - gen - COMMENT("move AND_RR->GPR") - and %2, %1.reg1, %1.reg2 + gen and %2, %1.reg1, %1.reg2 from OR_RR to GPR - gen - COMMENT("move OR_RR->GPR") - or %2, %1.reg1, %1.reg2 + gen or %2, %1.reg1, %1.reg2 from OR_RIS to GPR - gen - COMMENT("move OR_RIS->GPR") - oris %2, %1.reg, {CONST, %1.valhi} + gen oris %2, %1.reg, {CONST, %1.valhi} from OR_RC to GPR - gen - COMMENT("move OR_RC->GPR") - ori %2, %1.reg, {CONST, %1.val} + gen ori %2, %1.reg, {CONST, %1.val} from XOR_RR to GPR - gen - COMMENT("move XOR_RR->GPR") - xor %2, %1.reg1, %1.reg2 + gen xor %2, %1.reg1, %1.reg2 from XOR_RIS to GPR - gen - COMMENT("move XOR_RIS->GPR") - xoris %2, %1.reg, {CONST, %1.valhi} + gen xoris %2, %1.reg, {CONST, %1.valhi} from XOR_RC to GPR + gen xori %2, %1.reg, {CONST, %1.val} + +/* Conditions */ + + /* Compare values, then copy cr0 to GPR. */ + + from COND_RC to GPR gen - COMMENT("move XOR_RC->GPR") - xori %2, %1.reg, {CONST, %1.val} + cmpwi %1.reg, {CONST, %1.val} + mfcr %2 -/* Miscellaneous */ - - from OP_ALL_W + LABEL + CONST_ALL to GPRE + from COND_RR to GPR gen - move %1, %2.reg + cmpw %1.reg1, %1.reg2 + mfcr %2 + + from CONDL_RC to GPR + gen + cmplwi %1.reg, {CONST, %1.val} + mfcr %2 + + from CONDL_RR to GPR + gen + cmplw %1.reg1, %1.reg2 + mfcr %2 + + from COND_FS to GPR + gen + fcmpo CR0, %1.reg1, %1.reg2 + mfcr %2 + + from COND_FD to GPR + gen + fcmpo CR0, %1.reg1, %1.reg2 + mfcr %2 + + /* Given a copy of cr0 in %1.reg, extract a condition bit + * (lt, gt, eq) and perhaps flip it. + */ + + from XEQ to GPR + gen + extrwi %2, %1.reg, {CONST, 1}, {CONST, 2} + + from XNE to GPR + gen + extrwi %2, %1.reg, {CONST, 1}, {CONST, 2} + xori %2, %2, {CONST, 1} + + from XGT to GPR + gen + extrwi %2, %1.reg, {CONST, 1}, {CONST, 1} + + from XGE to GPR + gen + extrwi %2, %1.reg, {CONST, 1}, {CONST, 0} + xori %2, %2, {CONST, 1} + + from XLT to GPR + gen + extrwi %2, %1.reg, {CONST, 1}, {CONST, 0} + + from XLE to GPR + gen + extrwi %2, %1.reg, {CONST, 1}, {CONST, 1} + xori %2, %2, {CONST, 1} + +/* GPRE exists solely to allow us to use regvar() (which can only be used in + an expression) as a register constant. */ + + from ANY_BHW to GPRE + gen move %1, %2.reg + - TESTS - + + /* Given orX %1, %1, %1, ncgg says, "Instruction destroys %1, + * not allowed here". We use orX_readonly to trick ncgg. + * + * Using "or." and not "mr." because mach/powerpc/top/table + * was optimizing "or." and not "mr.". + */ to test GPR gen - orX RSCRATCH, %1, %1 - + orX_readonly %1, %1, %1 STACKINGRULES @@ -685,95 +641,57 @@ STACKINGRULES from LOCAL to STACK gen COMMENT("stack LOCAL") - stwu {GPRE, regvar(%1.off)}, {GPRINDIRECT, SP, 0-4} + stwu %1, {IND_RC_W, SP, 0-4} from REG to STACK gen COMMENT("stack REG") - stwu %1, {GPRINDIRECT, SP, 0-4} + stwu %1, {IND_RC_W, SP, 0-4} from REG_PAIR to STACK gen COMMENT("stack REG_PAIR") - stwu %1.2, {GPRINDIRECT, SP, 0-4} - stwu %1.1, {GPRINDIRECT, SP, 0-4} + stwu %1.2, {IND_RC_W, SP, 0-4} + stwu %1.1, {IND_RC_W, SP, 0-4} - from CONST_ALL + LABEL to STACK + from ANY_BHW-REG to STACK gen - COMMENT("stack CONST_ALL + LABEL") + COMMENT("stack ANY_BHW-REG") move %1, RSCRATCH - stwu RSCRATCH, {GPRINDIRECT, SP, 0-4} + stwu RSCRATCH, {IND_RC_W, SP, 0-4} - from SEX_B to STACK - gen - COMMENT("stack SEX_B") - extsb RSCRATCH, %1.reg - stwu RSCRATCH, {GPRINDIRECT, SP, 0-4} - - from SEX_H to STACK - gen - COMMENT("stack SEX_H") - extsh RSCRATCH, %1.reg - stwu RSCRATCH, {GPRINDIRECT, SP, 0-4} - - from SUM_ALL + TRISTATE_ALL + LOGICAL_ALL to STACK - gen - COMMENT("stack SUM_ALL + TRISTATE_ALL + LOGICAL_ALL") - move %1, RSCRATCH - stwu RSCRATCH, {GPRINDIRECT, SP, 0-4} - - from IND_ALL_BHW to STACK - gen - COMMENT("stack IND_ALL_BHW") - move %1, RSCRATCH - stwu RSCRATCH, {GPRINDIRECT, SP, 0-4} - from IND_ALL_D to STACK gen COMMENT("stack IND_ALL_D") move %1, FSCRATCH - stfdu FSCRATCH, {GPRINDIRECT, SP, 0-8} - + stfdu FSCRATCH, {IND_RC_D, SP, 0-8} + from FREG to STACK gen COMMENT("stack FPR") - stfdu %1, {GPRINDIRECT, SP, 0-8} - + stfdu %1, {IND_RC_D, SP, 0-8} + from FSREG to STACK gen COMMENT("stack FSREG") - stfsu %1, {GPRINDIRECT, SP, 0-4} + stfsu %1, {IND_RC_W, SP, 0-4} COERCIONS - from REG + from ANY_BHW uses REG gen - COMMENT("coerce REG->REG") + COMMENT("coerce ANY_BHW->REG") move %1, %a yields %a - from CONST_ALL - uses REG - gen - COMMENT("coerce CONST_ALL->REG") - move %1, %a - yields %a - - from LABEL - uses REG - gen - COMMENT("coerce LABEL->REG") - move %1, %a - yields %a - from STACK uses REG gen COMMENT("coerce STACK->REG") - lwz %a, {GPRINDIRECT, SP, 0} + lwz %a, {IND_RC_W, SP, 0} addi SP, SP, {CONST, 4} yields %a @@ -781,48 +699,28 @@ COERCIONS uses REG_PAIR gen COMMENT("coerce STACK->REG_PAIR") - lwz %a.1, {GPRINDIRECT, SP, 0} - lwz %a.2, {GPRINDIRECT, SP, 4} + lwz %a.1, {IND_RC_W, SP, 0} + lwz %a.2, {IND_RC_W, SP, 4} addi SP, SP, {CONST, 8} yields %a - from SEX_B - uses REG - gen - COMMENT("coerce SEX_B->REG") - extsb %a, %1.reg - yields %a - - from SEX_H - uses REG - gen - COMMENT("coerce SEX_H->REG") - extsh %a, %1.reg - yields %a - - from SUM_ALL + TRISTATE_ALL + LOGICAL_ALL - uses REG - gen - move %1, %a - yields %a - from FSREG uses FSREG gen fmr %a, %1 yields %a - + from FREG uses FREG gen fmr %a, %1 yields %a - + from STACK uses FREG gen COMMENT("coerce STACK->FREG") - lfd %a, {GPRINDIRECT, SP, 0} + lfd %a, {IND_RC_D, SP, 0} addi SP, SP, {CONST, 8} yields %a @@ -830,16 +728,10 @@ COERCIONS uses FSREG gen COMMENT("coerce STACK->FSREG") - lfs %a, {GPRINDIRECT, SP, 0} + lfs %a, {IND_RC_W, SP, 0} addi SP, SP, {CONST, 4} yields %a - from IND_ALL_BHW - uses REG - gen - move %1, %a - yields %a - from IND_ALL_W uses FSREG gen @@ -884,17 +776,17 @@ PATTERNS yields %1 %1 with FSREG yields %1 %1 - + pat dup $1==INT64 /* Duplicate double-word on top of stack */ with REG REG yields %2 %1 %2 %1 with FREG yields %1 %1 - + pat exg $1==INT32 /* Exchange top two words on stack */ with REG REG yields %1 %2 - + pat stl lol $1==$2 /* Store then load local */ leaving dup 4 @@ -910,33 +802,21 @@ PATTERNS dup INT32 lal $1 sti $2 - + pat ste loe $1==$2 /* Store then load external */ leaving dup 4 ste $1 - - + + /* Type conversions */ - pat loc loc cii loc loc cii $1==$4 && $2==$5 /* madness, generated by the C compiler */ - leaving - loc $1 - loc $2 - cii - - pat loc loc cii loc loc cii $2==INT32 && $5==INT32 && $4<$2 /* madness, generated by the C compiler */ - leaving - loc $4 - loc $5 - cii - pat loc loc ciu /* signed X -> unsigned X */ leaving loc $1 loc $2 cuu - + pat loc loc cuu $1==$2 /* unsigned X -> unsigned X */ /* nop */ @@ -945,25 +825,22 @@ PATTERNS pat loc loc cui $1==$2 /* unsigned X -> signed X */ /* nop */ - + pat loc loc cui $1==INT8 && $2==INT32 /* unsigned char -> signed int */ /* nop */ - + pat loc loc cui $1==INT16 && $2==INT32 /* unsigned short -> signed int */ /* nop */ - - pat loc loc cii $1==INT8 && $2==INT32 /* signed char -> signed int */ - with GPR - yields {SEX_B, %1} - - pat loc loc cii $1==2 && $2==4 /* signed char -> signed short */ - with GPR - yields {SEX_H, %1} - - - - + pat loc loc cii $1==INT8 && $2==INT32 /* signed char -> signed int */ + with REG + yields {SEX_B, %1} + + pat loc loc cii $1==2 && $2==4 /* signed char -> signed short */ + with REG + yields {SEX_H, %1} + + /* Local variables */ pat lal smalls($1) /* Load address of local */ @@ -975,7 +852,7 @@ PATTERNS pat lol inreg($1)>0 /* Load from local */ yields {LOCAL, $1} - + pat lol /* Load from local */ leaving lal $1 @@ -985,34 +862,31 @@ PATTERNS leaving lal $1 loi INT32*2 - + pat stl inreg($1)>0 /* Store to local */ - with CONST_ALL + LABEL + GPR + OP_ALL_W + with ANY_BHW kills regvar($1), LOCAL %off==$1 gen move %1, {GPRE, regvar($1)} - + pat stl /* Store to local */ leaving lal $1 sti INT32 - + pat sdl /* Store double-word to local */ leaving lal $1 sti INT32*2 - + pat lil inreg($1)>0 /* Load from indirected local */ - uses REG - gen - lwz %a, {GPRINDIRECT, regvar($1), 0} - yields %a - + yields {IND_RC_W, regvar($1), 0} + pat lil /* Load from indirected local */ leaving lol $1 loi INT32 - + pat sil /* Save to indirected local */ leaving lol $1 @@ -1022,14 +896,14 @@ PATTERNS leaving loc 0 stl $1 - + pat inl /* Increment local */ leaving lol $1 loc 1 adi 4 stl $1 - + pat del /* Decrement local */ leaving lol $1 @@ -1039,14 +913,15 @@ PATTERNS /* Global variables */ - + pat lpi /* Load address of external function */ leaving lae $1 - + pat lae /* Load address of external */ - yields {LABEL, $1} - + uses REG={LABEL_HA, $1} + yields {SUM_RL, %a, $1} + pat loe /* Load word external */ leaving lae $1 @@ -1056,36 +931,33 @@ PATTERNS leaving lae $1 sti INT32 - + pat lde /* Load double-word external */ leaving lae $1 loi INT64 - + pat sde /* Store double-word external */ leaving lae $1 sti INT64 - + pat zre /* Zero external */ leaving loc 0 ste $1 - + pat ine /* Increment external */ - uses REG={LABEL, $1}, REG - gen - lwz %b, {GPRINDIRECT, %a, 0} - addi %b, %b, {CONST, 1} - stw %b, {GPRINDIRECT, %a, 0} - + leaving + loe $1 + inc + ste $1 + pat dee /* Decrement external */ - uses REG={LABEL, $1}, REG - gen - lwz %b, {GPRINDIRECT, %a, 0} - addi %b, %b, {CONST, 0-1} - stw %b, {GPRINDIRECT, %a, 0} - + leaving + loe $1 + dec + ste $1 /* Structures */ @@ -1094,157 +966,142 @@ PATTERNS leaving adp $1 loi INT32 - + pat ldf /* Load double-word offsetted */ leaving adp $1 loi INT64 - + pat stf /* Store word offsetted */ leaving adp $1 sti INT32 - + pat sdf /* Store double-word offsetted */ leaving adp $1 sti INT64 - /* Loads and stores */ pat loi $1==INT8 /* Load byte indirect */ - with GPR + with REG yields {IND_RC_B, %1, 0} - with SUM_RR - yields {IND_RR_B, %1.reg1, %1.reg2} - with SUM_RC + with exact SUM_RC yields {IND_RC_B, %1.reg, %1.off} + with exact SUM_RL + yields {IND_RL_B, %1.reg, %1.adr} + with exact SUM_RR + yields {IND_RR_B, %1.reg1, %1.reg2} pat loi loc loc cii $1==INT16 && $2==INT16 && $3==INT32 /* Load half-word indirect and sign extend */ - with GPR + with REG yields {IND_RC_H_S, %1, 0} - with SUM_RR - yields {IND_RR_H_S, %1.reg1, %1.reg2} - with SUM_RC + with exact SUM_RC yields {IND_RC_H_S, %1.reg, %1.off} + with exact SUM_RL + yields {IND_RL_H_S, %1.reg, %1.adr} + with exact SUM_RR + yields {IND_RR_H_S, %1.reg1, %1.reg2} pat loi $1==INT16 /* Load half-word indirect */ - with GPR + with REG yields {IND_RC_H, %1, 0} - with SUM_RR - yields {IND_RR_H, %1.reg1, %1.reg2} - with SUM_RC + with exact SUM_RC yields {IND_RC_H, %1.reg, %1.off} + with exact SUM_RL + yields {IND_RL_H, %1.reg, %1.adr} + with exact SUM_RR + yields {IND_RR_H, %1.reg1, %1.reg2} pat loi $1==INT32 /* Load word indirect */ - with GPR + with REG yields {IND_RC_W, %1, 0} - with SUM_RC + with exact SUM_RC yields {IND_RC_W, %1.reg, %1.off} - with SUM_RR + with exact SUM_RL + yields {IND_RL_W, %1.reg, %1.adr} + with exact SUM_RR yields {IND_RR_W, %1.reg1, %1.reg2} pat loi $1==INT64 /* Load double-word indirect */ - with GPR + with REG yields {IND_RC_D, %1, 0} - with SUM_RC + with exact SUM_RC yields {IND_RC_D, %1.reg, %1.off} - with SUM_RR + with exact SUM_RL + yields {IND_RL_D, %1.reg, %1.adr} + with exact SUM_RR yields {IND_RR_D, %1.reg1, %1.reg2} pat loi /* Load arbitrary size */ leaving loc $1 los INT32 - - pat los /* Load arbitrary size */ + + pat los $1==INT32 /* Load arbitrary size */ with GPR3 GPR4 STACK kills ALL gen bl {LABEL, ".los"} pat sti $1==INT8 /* Store byte indirect */ - with GPR GPR + with REG REG kills MEMORY - gen - stb %2, {GPRINDIRECT, %1, 0} - with SUM_RR GPR + gen move %2, {IND_RC_B, %1, 0} + with SUM_RC REG kills MEMORY - gen - stbx %2, %1.reg1, %1.reg2 - with SUM_RC GPR + gen move %2, {IND_RC_B, %1.reg, %1.off} + with SUM_RL REG kills MEMORY - gen - move %2, {IND_RC_B, %1.reg, %1.off} - with GPR SEX_B + gen move %2, {IND_RL_B, %1.reg, %1.adr} + with SUM_RR REG kills MEMORY - gen - stb %2.reg, {GPRINDIRECT, %1, 0} - with SUM_RR SEX_B - kills MEMORY - gen - stbx %2.reg, %1.reg1, %1.reg2 - with SUM_RC SEX_B - kills MEMORY - gen - move %2.reg, {IND_RC_B, %1.reg, %1.off} + gen move %2, {IND_RR_B, %1.reg1, %1.reg2} pat sti $1==INT16 /* Store half-word indirect */ - with GPR GPR + with REG REG kills MEMORY - gen - sth %2, {GPRINDIRECT, %1, 0} - with SUM_RR GPR + gen move %2, {IND_RC_H, %1, 0} + with SUM_RC REG kills MEMORY - gen - sthx %2, %1.reg1, %1.reg2 - with SUM_RC GPR + gen move %2, {IND_RC_H, %1.reg, %1.off} + with SUM_RL REG kills MEMORY - gen - move %2, {IND_RC_H, %1.reg, %1.off} - with GPR SEX_H + gen move %2, {IND_RL_H, %1.reg, %1.adr} + with SUM_RR REG kills MEMORY - gen - sth %2.reg, {GPRINDIRECT, %1, 0} - with SUM_RR SEX_H - kills MEMORY - gen - sthx %2.reg, %1.reg1, %1.reg2 - with SUM_RC SEX_H - kills MEMORY - gen - move %2.reg, {IND_RC_H, %1.reg, %1.off} + gen move %2, {IND_RR_H, %1.reg1, %1.reg2} pat sti $1==INT32 /* Store word indirect */ - with GPR GPR+FSREG + with REG REG+FSREG kills MEMORY - gen - move %2, {IND_RC_W, %1, 0} - with SUM_RR GPR+FSREG + gen move %2, {IND_RC_W, %1, 0} + with SUM_RC REG+FSREG kills MEMORY - gen - move %2, {IND_RR_W, %1.reg1, %1.reg2} - with SUM_RC GPR+FSREG + gen move %2, {IND_RC_W, %1.reg, %1.off} + with SUM_RL REG+FSREG kills MEMORY - gen - move %2, {IND_RC_W, %1.reg, %1.off} + gen move %2, {IND_RL_W, %1.reg, %1.adr} + with SUM_RR REG+FSREG + kills MEMORY + gen move %2, {IND_RR_W, %1.reg1, %1.reg2} pat sti $1==INT64 /* Store double-word indirect */ with REG FREG kills MEMORY - gen - move %2, {IND_RC_D, %1, 0} - with SUM_RR FREG - kills MEMORY - gen - move %2, {IND_RR_D, %1.reg1, %1.reg2} + gen move %2, {IND_RC_D, %1, 0} with SUM_RC FREG kills MEMORY - gen - move %2, {IND_RC_D, %1.reg, %1.off} + gen move %2, {IND_RC_D, %1.reg, %1.off} + with SUM_RL FREG + kills MEMORY + gen move %2, {IND_RL_D, %1.reg, %1.adr} + with SUM_RR FREG + kills MEMORY + gen move %2, {IND_RR_D, %1.reg1, %1.reg2} /* * This pattern would be too slow: * with REG REG REG @@ -1283,22 +1140,21 @@ PATTERNS loc $1 sts INT32 - pat sts /* Store arbitrary size */ + pat sts $1==INT32 /* Store arbitrary size */ with GPR3 GPR4 STACK kills ALL gen bl {LABEL, ".sts"} - /* Arithmetic wrappers */ pat ads $1==4 /* Add var to pointer */ leaving adi $1 - + pat sbs $1==4 /* Subtract var from pointer */ leaving sbi $1 - + pat adp /* Add constant to pointer */ leaving loc $1 @@ -1307,41 +1163,30 @@ PATTERNS pat adu /* Add unsigned */ leaving adi $1 - + pat sbu /* Subtract unsigned */ leaving sbi $1 - + pat inc /* Add 1 */ leaving loc 1 adi 4 - + pat dec /* Subtract 1 */ leaving loc 1 sbi 4 - - pat loc mlu $2==2 /* Unsigned multiply by constant */ - leaving - loc $1 - mli 4 - - pat mlu /* Unsigned multiply by var */ + + pat mlu /* Multiply unsigned */ leaving mli $1 - - pat loc slu /* Shift left unsigned by constant amount */ - leaving - loc $1 - sli $2 - - pat slu /* Shift left unsigned by variable amount */ + + pat slu /* Shift left unsigned */ leaving sli $1 - - + /* Word arithmetic */ pat adi $1==4 /* Add word (second + top) */ @@ -1357,14 +1202,12 @@ PATTERNS with REG CONST_HZ uses reusing %1, REG={SUM_RIS, %1, his(%2.val)} yields %a - with CONST_ALL-CONST2-CONST_HZ REG + with CONST_STACK-CONST2-CONST_HZ REG uses reusing %2, REG={SUM_RIS, %2, his(%1.val)} yields {SUM_RC, %a, los(%1.val)} - with REG CONST_ALL-CONST2-CONST_HZ + with REG CONST_STACK-CONST2-CONST_HZ uses reusing %1, REG={SUM_RIS, %1, his(%2.val)} yields {SUM_RC, %a, los(%2.val)} - with CONST_ALL LABEL - yields {LABEL, %2.adr+%1.val} pat sbi $1==4 /* Subtract word (second - top) */ with REG REG @@ -1377,11 +1220,9 @@ PATTERNS with CONST_HZ REG uses reusing %2, REG={SUM_RIS, %2, his(0-%1.val)} yields %a - with CONST_ALL-CONST2_WHEN_NEG-CONST_HZ REG + with CONST_STACK-CONST2_WHEN_NEG-CONST_HZ REG uses reusing %2, REG={SUM_RIS, %2, his(0-%1.val)} yields {SUM_RC, %a, los(0-%1.val)} - with CONST_ALL LABEL - yields {LABEL, %2.adr+(0-%1.val)} pat ngi $1==4 /* Negate word */ with REG @@ -1389,21 +1230,21 @@ PATTERNS gen neg %a, %1 yields %a - + pat mli $1==4 /* Multiply word (second * top) */ with REG REG uses reusing %2, REG gen mullw %a, %2, %1 yields %a - + pat dvi $1==4 /* Divide word (second / top) */ with REG REG uses reusing %2, REG gen divw %a, %2, %1 yields %a - + pat dvu $1==4 /* Divide unsigned word (second / top) */ with REG REG uses reusing %2, REG @@ -1419,7 +1260,7 @@ PATTERNS mullw %a, %a, %1 subf %a, %a, %2 yields %a - + pat rmu $1==4 /* Remainder unsigned word (second % top) */ with REG REG uses REG @@ -1430,43 +1271,47 @@ PATTERNS yields %a pat and $1==4 /* AND word */ - with GPR NOT_R + with REG NOT_R uses reusing %1, REG gen andc %a, %1, %2.reg yields %a - with NOT_R GPR + with NOT_R REG uses reusing %1, REG gen andc %a, %2, %1.reg yields %a - with GPR GPR + with REG REG yields {AND_RR, %1, %2} - with GPR UCONST2 + with REG UCONST2 uses reusing %1, REG gen andiX %a, %1, {CONST, %2.val} yields %a - with UCONST2 GPR + with UCONST2 REG uses reusing %2, REG gen andiX %a, %2, {CONST, %1.val} yields %a - with GPR CONST_HZ + with REG CONST_HZ uses reusing %1, REG gen andisX %a, %1, {CONST, hi(%2.val)} yields %a - with CONST_HZ GPR + with CONST_HZ REG uses reusing %2, REG gen andisX %a, %2, {CONST, hi(%1.val)} yields %a - pat and !defined($1) /* AND set */ - with STACK - gen - bl {LABEL, ".and"} + pat and defined($1) /* AND set */ + leaving + loc $1 + cal ".and" + + pat and !defined($1) + leaving + cal ".and" pat ior $1==4 /* OR word */ with REG NOT_R @@ -1491,17 +1336,22 @@ PATTERNS with CONST_HZ REG uses reusing %2, REG={OR_RIS, %2, hi(%1.val)} yields %a - with REG CONST_ALL-UCONST2-CONST_HZ + with REG CONST_STACK-UCONST2-CONST_HZ uses reusing %1, REG={OR_RIS, %1, hi(%2.val)} yields {OR_RC, %1, lo(%2.val)} - with CONST_ALL-UCONST2-CONST_HZ REG + with CONST_STACK-UCONST2-CONST_HZ REG uses reusing %2, REG={OR_RIS, %2, hi(%1.val)} yields {OR_RC, %2, lo(%1.val)} - pat ior !defined($1) /* OR set */ - with STACK - gen - bl {LABEL, ".ior"} + pat ior defined($1) /* OR set */ + leaving + loc $1 + cal ".ior" + + /* OR set (variable), used in lang/m2/libm2/LtoUset.e */ + pat ior !defined($1) + leaving + cal ".ior" pat xor $1==4 /* XOR word */ with REG REG @@ -1516,18 +1366,20 @@ PATTERNS with CONST_HZ REG uses reusing %2, REG={XOR_RIS, %2, hi(%1.val)} yields %a - with REG CONST_ALL-UCONST2-CONST_HZ + with REG CONST_STACK-UCONST2-CONST_HZ uses reusing %1, REG={XOR_RIS, %1, hi(%2.val)} yields {XOR_RC, %1, lo(%2.val)} - with CONST_ALL-UCONST2-CONST_HZ REG + with CONST_STACK-UCONST2-CONST_HZ REG uses reusing %2, REG={XOR_RIS, %2, hi(%1.val)} yields {XOR_RC, %2, lo(%1.val)} - pat xor !defined($1) /* XOR set */ + pat xor defined($1) /* XOR set */ with STACK + kills ALL gen + move {CONST, $1}, R3 bl {LABEL, ".xor"} - + pat com $1==INT32 /* NOT word */ with AND_RR uses REG @@ -1544,72 +1396,86 @@ PATTERNS gen eqv %a, %1.reg1, %1.reg2 yields %a - with GPR + with REG yields {NOT_R, %1} - - pat com !defined($1) /* NOT set */ - with STACK - gen - bl {LABEL, ".com"} - + + pat com defined($1) /* NOT set */ + leaving + loc $1 + cal ".com" + + pat com !defined($1) + leaving + cal ".com" + + pat zer $1==4 /* Push zero */ + leaving + loc 0 + + pat zer defined($1) /* Create empty set */ + leaving + loc $1 + cal ".zer" + pat sli $1==4 /* Shift left (second << top) */ - with CONST_ALL GPR + with CONST_STACK REG uses reusing %2, REG gen rlwinm %a, %2, {CONST, (%1.val & 0x1F)}, {CONST, 0}, {CONST, 31-(%1.val & 0x1F)} yields %a - with GPR GPR + with REG REG uses reusing %2, REG gen slw %a, %2, %1 yields %a - + pat sri $1==4 /* Shift right signed (second >> top) */ - with CONST_ALL GPR + with CONST_STACK REG uses reusing %2, REG gen srawi %a, %2, {CONST, %1.val & 0x1F} yields %a - with GPR GPR + with REG REG uses reusing %2, REG gen sraw %a, %2, %1 yields %a pat sru $1==4 /* Shift right unsigned (second >> top) */ - with CONST_ALL GPR + with CONST_STACK REG uses reusing %2, REG gen rlwinm %a, %2, {CONST, 32-(%1.val & 0x1F)}, {CONST, (%1.val & 0x1F)}, {CONST, 31} yields %a - with GPR GPR + with REG REG uses reusing %2, REG gen srw %a, %2, %1 yields %a - + /* Arrays */ pat aar $1==INT32 /* Index array */ with GPR3 GPR4 GPR5 + kills ALL gen bl {LABEL, ".aar4"} yields R3 - + pat lae lar $2==INT32 && nicesize(rom($1, 3)) /* Load array */ leaving lae $1 aar INT32 loi rom($1, 3) - + pat lar $1==INT32 /* Load array */ with GPR3 GPR4 GPR5 STACK kills ALL gen bl {LABEL, ".lar4"} - + pat lae sar $2==INT32 && nicesize(rom($1, 3)) /* Store array */ leaving lae $1 @@ -1621,224 +1487,408 @@ PATTERNS kills ALL gen bl {LABEL, ".sar4"} - - /* Sets */ - pat set defined($1) /* Create word with set bit */ + pat set defined($1) /* Create singleton set */ leaving - loc 1 - exg INT32 - sli INT32 - - pat set !defined($1) /* Create structure with set bit (variable) */ - with GPR3 GPR4 STACK - gen - bl {LABEL, ".set"} - - pat inn /* Test for set bit */ - with STACK - kills ALL - uses REG - gen - li32 %a, {CONST, $1} - stwu %a, {GPRINDIRECT, SP, 0-4} - bl {LABEL, ".inn"} - - - + loc $1 + cal ".set" + + /* Create set (variable), used in lang/m2/libm2/LtoUset.e */ + pat set !defined($1) + leaving + cal ".set" + + pat inn defined($1) /* Test for set bit */ + leaving + loc $1 + cal ".inn" + + pat inn !defined($1) + leaving + cal ".inn" + + /* Boolean resolutions */ pat teq /* top = (top == 0) */ - with TRISTATE_ALL + GPR + with REG uses reusing %1, REG gen - move %1, C0 - move C0, RSCRATCH - move {LABEL, ".teq_table"}, %a - lwzx %a, %a, RSCRATCH + test %1 + mfcr %a + move {XEQ, %a}, %a yields %a - + pat tne /* top = (top != 0) */ - with TRISTATE_ALL + GPR + with REG uses reusing %1, REG gen - move %1, C0 - move C0, RSCRATCH - move {LABEL, ".tne_table"}, %a - lwzx %a, %a, RSCRATCH + test %1 + mfcr %a + move {XNE, %a}, %a yields %a - + pat tlt /* top = (top < 0) */ - with TRISTATE_ALL + GPR + with REG uses reusing %1, REG gen - move %1, C0 - move C0, RSCRATCH - move {LABEL, ".tlt_table"}, %a - lwzx %a, %a, RSCRATCH + test %1 + mfcr %a + move {XLT, %a}, %a yields %a - + pat tle /* top = (top <= 0) */ - with TRISTATE_ALL + GPR + with REG uses reusing %1, REG gen - move %1, C0 - move C0, RSCRATCH - move {LABEL, ".tle_table"}, %a - lwzx %a, %a, RSCRATCH + test %1 + mfcr %a + move {XLE, %a}, %a yields %a - + pat tgt /* top = (top > 0) */ - with TRISTATE_ALL + GPR + with REG uses reusing %1, REG gen - move %1, C0 - move C0, RSCRATCH - move {LABEL, ".tgt_table"}, %a - lwzx %a, %a, RSCRATCH + test %1 + mfcr %a + move {XGT, %a}, %a yields %a pat tge /* top = (top >= 0) */ - with TRISTATE_ALL + GPR + with REG uses reusing %1, REG gen - move %1, C0 - move C0, RSCRATCH - move {LABEL, ".tge_table"}, %a - lwzx %a, %a, RSCRATCH + test %1 + mfcr %a + move {XGE, %a}, %a yields %a - + pat cmi teq $1==4 /* Signed second == top */ + with REG CONST2 + uses reusing %1, REG={COND_RC, %1, %2.val} + gen move {XEQ, %a}, %a + yields %a + with CONST2 REG + uses reusing %1, REG={COND_RC, %2, %1.val} + gen move {XEQ, %a}, %a + yields %a + with REG REG + uses reusing %1, REG={COND_RR, %2, %1} + gen move {XEQ, %a}, %a + yields %a + + pat cmi tne $1==4 /* Signed second != top */ + with REG CONST2 + uses reusing %1, REG={COND_RC, %1, %2.val} + gen move {XNE, %a}, %a + yields %a + with CONST2 REG + uses reusing %1, REG={COND_RC, %2, %1.val} + gen move {XNE, %a}, %a + yields %a + with REG REG + uses reusing %1, REG={COND_RR, %2, %1} + gen move {XNE, %a}, %a + yields %a + + pat cmi tgt $1==4 /* Signed second > top */ + with REG CONST2 + uses reusing %1, REG={COND_RC, %1, %2.val} + gen move {XLT, %a}, %a + yields %a + with CONST2 REG + uses reusing %1, REG={COND_RC, %2, %1.val} + gen move {XGT, %a}, %a + yields %a + with REG REG + uses reusing %1, REG={COND_RR, %2, %1} + gen move {XGT, %a}, %a + yields %a + + pat cmi tge $1==4 /* Signed second >= top */ + with REG CONST2 + uses reusing %1, REG={COND_RC, %1, %2.val} + gen move {XLE, %a}, %a + yields %a + with CONST2 REG + uses reusing %1, REG={COND_RC, %2, %1.val} + gen move {XGE, %a}, %a + yields %a + with REG REG + uses reusing %1, REG={COND_RR, %2, %1} + gen move {XGE, %a}, %a + yields %a + + pat cmi tlt $1==4 /* Signed second < top */ + with REG CONST2 + uses reusing %1, REG={COND_RC, %1, %2.val} + gen move {XGT, %a}, %a + yields %a + with CONST2 REG + uses reusing %1, REG={COND_RC, %2, %1.val} + gen move {XLT, %a}, %a + yields %a + with REG REG + uses reusing %1, REG={COND_RR, %2, %1} + gen move {XLT, %a}, %a + yields %a + + pat cmi tle $1==4 /* Signed second <= top */ + with REG CONST2 + uses reusing %1, REG={COND_RC, %1, %2.val} + gen move {XGE, %a}, %a + yields %a + with CONST2 REG + uses reusing %1, REG={COND_RC, %2, %1.val} + gen move {XLE, %a}, %a + yields %a + with REG REG + uses reusing %1, REG={COND_RR, %2, %1} + gen move {XLE, %a}, %a + yields %a + + pat cmu teq $1==4 /* Unsigned second == top */ + with REG UCONST2 + uses reusing %1, REG={CONDL_RC, %1, %2.val} + gen move {XEQ, %a}, %a + yields %a + with UCONST2 REG + uses reusing %1, REG={CONDL_RC, %2, %1.val} + gen move {XEQ, %a}, %a + yields %a + with REG REG + uses reusing %1, REG={CONDL_RR, %2, %1} + gen move {XEQ, %a}, %a + yields %a + + pat cmu tne $1==4 /* Unsigned second != top */ + with REG UCONST2 + uses reusing %1, REG={CONDL_RC, %1, %2.val} + gen move {XNE, %a}, %a + yields %a + with UCONST2 REG + uses reusing %1, REG={CONDL_RC, %2, %1.val} + gen move {XNE, %a}, %a + yields %a + with REG REG + uses reusing %1, REG={CONDL_RR, %2, %1} + gen move {XNE, %a}, %a + yields %a + + pat cmu tgt $1==4 /* Unsigned second > top */ + with REG UCONST2 + uses reusing %1, REG={CONDL_RC, %1, %2.val} + gen move {XLT, %a}, %a + yields %a + with UCONST2 REG + uses reusing %1, REG={CONDL_RC, %2, %1.val} + gen move {XGT, %a}, %a + yields %a + with REG REG + uses reusing %1, REG={CONDL_RR, %2, %1} + gen move {XGT, %a}, %a + yields %a + + pat cmu tge $1==4 /* Unsigned second >= top */ + with REG UCONST2 + uses reusing %1, REG={CONDL_RC, %1, %2.val} + gen move {XLE, %a}, %a + yields %a + with UCONST2 REG + uses reusing %1, REG={CONDL_RC, %2, %1.val} + gen move {XGE, %a}, %a + yields %a + with REG REG + uses reusing %1, REG={CONDL_RR, %2, %1} + gen move {XGE, %a}, %a + yields %a + + pat cmu tlt $1==4 /* Unsigned second < top */ + with REG UCONST2 + uses reusing %1, REG={CONDL_RC, %1, %2.val} + gen move {XGT, %a}, %a + yields %a + with UCONST2 REG + uses reusing %1, REG={CONDL_RC, %2, %1.val} + gen move {XLT, %a}, %a + yields %a + with REG REG + uses reusing %1, REG={CONDL_RR, %2, %1} + gen move {XLT, %a}, %a + yields %a + + pat cmu tle $1==4 /* Unsigned second <= top */ + with REG UCONST2 + uses reusing %1, REG={CONDL_RC, %1, %2.val} + gen move {XGE, %a}, %a + yields %a + with UCONST2 REG + uses reusing %1, REG={CONDL_RC, %2, %1.val} + gen move {XLE, %a}, %a + yields %a + with REG REG + uses reusing %1, REG={CONDL_RR, %2, %1} + gen move {XLE, %a}, %a + yields %a /* Simple branches */ - pat zeq /* Branch if signed top == 0 */ - with TRISTATE_ALL+GPR STACK + proc zxx example zeq + with REG STACK gen - move %1, C0 - bc IFTRUE, EQ, {LABEL, $1} + test %1 + bxx* {LABEL, $1} - pat beq - leaving - cmi INT32 - zeq $1 - - pat zne /* Branch if signed top != 0 */ - with TRISTATE_ALL+GPR STACK + /* Pop signed int, branch if... */ + pat zeq call zxx("beq") /* top == 0 */ + pat zne call zxx("bne") /* top != 0 */ + pat zgt call zxx("bgt") /* top > 0 */ + pat zge call zxx("bge") /* top >= 0 */ + pat zlt call zxx("blt") /* top < 0 */ + pat zle call zxx("ble") /* top >= 0 */ + + /* The peephole optimizer rewrites + * cmi 4 zeq + * as beq, and does same for bne, bgt, and so on. + */ + + proc bxx example beq + with REG CONST2 STACK gen - move %1, C0 - bc IFFALSE, EQ, {LABEL, $1} - - pat bne - leaving - cmi INT32 - zne $1 - - pat zgt /* Branch if signed top > 0 */ - with TRISTATE_ALL+GPR STACK + cmpwi %1, {CONST, %2.val} + bxx[2] {LABEL, $1} + with CONST2 REG STACK gen - move %1, C0 - bc IFTRUE, GT, {LABEL, $1} - - pat bgt - leaving - cmi INT32 - zgt $1 - - pat zge /* Branch if signed top >= 0 */ - with TRISTATE_ALL+GPR STACK + cmpwi %2, {CONST, %1.val} + bxx[1] {LABEL, $1} + with REG REG STACK gen - move %1, C0 - bc IFFALSE, LT, {LABEL, $1} + cmpw %2, %1 + bxx[1] {LABEL, $1} - pat bge - leaving - cmi INT32 - zge $1 - - pat zlt /* Branch if signed top < 0 */ - with TRISTATE_ALL+GPR STACK + /* Pop two signed ints, branch if... */ + pat beq call bxx("beq", "beq") /* second == top */ + pat bne call bxx("bne", "bne") /* second != top */ + pat bgt call bxx("bgt", "blt") /* second > top */ + pat bge call bxx("bge", "ble") /* second >= top */ + pat blt call bxx("blt", "bgt") /* second < top */ + pat ble call bxx("ble", "bge") /* second >= top */ + + proc cmu4zxx example cmu zeq + with REG CONST2 STACK gen - move %1, C0 - bc IFTRUE, LT, {LABEL, $1} - - pat blt - leaving - cmi INT32 - zlt $1 - - pat zle /* Branch if signed top >= 0 */ - with TRISTATE_ALL+GPR STACK + cmplwi %1, {CONST, %2.val} + bxx[2] {LABEL, $2} + with CONST2 REG STACK gen - move %1, C0 - bc IFFALSE, GT, {LABEL, $1} + cmplwi %2, {CONST, %1.val} + bxx[1] {LABEL, $2} + with REG REG STACK + gen + cmplw %2, %1 + bxx[1] {LABEL, $2} - pat ble - leaving - cmi INT32 - zle $1 - + /* Pop two unsigned ints, branch if... */ + pat cmu zeq $1==4 call cmu4zxx("beq", "beq") + pat cmu zne $1==4 call cmu4zxx("bne", "bne") + pat cmu zgt $1==4 call cmu4zxx("bgt", "blt") + pat cmu zge $1==4 call cmu4zxx("bge", "ble") + pat cmu zlt $1==4 call cmu4zxx("blt", "bgt") + pat cmu zle $1==4 call cmu4zxx("ble", "bge") -/* Compare and jump */ - pat cmi /* Signed tristate compare */ - with CONST_ALL GPR - yields {TRISTATE_RC_S, %2, %1.val} - with GPR GPR - yields {TRISTATE_RR_S, %2, %1} - - pat cmu /* Unsigned tristate compare */ - with CONST_ALL GPR - yields {TRISTATE_RC_U, %2, %1.val} - with GPR GPR - yields {TRISTATE_RR_U, %2, %1} - +/* Comparisons */ + + /* Each comparison extracts the lt and gt bits from cr0. + * extlwi %a, %a, 2, 0 + * puts lt in the sign bit, so lt yields a negative result, + * gt yields positive. + * rlwinm %a, %a, 1, 31, 0 + * puts gt in the sign bit, to reverse the comparison. + */ + + pat cmi $1==INT32 /* Signed tristate compare */ + with REG CONST2 + uses reusing %1, REG={COND_RC, %1, %2.val} + gen rlwinm %a, %a, {CONST, 1}, {CONST, 31}, {CONST, 0} + yields %a + with CONST2 REG + uses reusing %2, REG={COND_RC, %2, %1.val} + gen extlwi %a, %a, {CONST, 2}, {CONST, 0} + yields %a + with REG REG + uses reusing %1, REG={COND_RR, %2, %1} + gen extlwi %a, %a, {CONST, 2}, {CONST, 0} + yields %a + + pat cmu $1==INT32 /* Unsigned tristate compare */ + with REG UCONST2 + uses reusing %1, REG={CONDL_RC, %1, %2.val} + gen rlwinm %a, %a, {CONST, 1}, {CONST, 31}, {CONST, 0} + yields %a + with UCONST2 REG + uses reusing %2, REG={CONDL_RC, %2, %1.val} + gen extlwi %a, %a, {CONST, 2}, {CONST, 0} + yields %a + with REG REG + uses reusing %1, REG={CONDL_RR, %2, %1} + gen extlwi %a, %a, {CONST, 2}, {CONST, 0} + yields %a + pat cmp /* Compare pointers */ leaving cmu INT32 - + pat cms $1==INT32 /* Compare blocks (word sized) */ leaving cmi INT32 - - - + + pat cms defined($1) + with STACK + kills ALL + gen + move {CONST, $1}, R3 + bl {LABEL, ".cms"} + yields R3 + /* Other branching and labelling */ pat lab topeltsize($1)==4 && !fallthrough($1) + kills ALL gen labeldef $1 yields R3 - + pat lab topeltsize($1)==4 && fallthrough($1) - with GPR3 + with GPR3 STACK + kills ALL gen labeldef $1 yields %1 - + pat lab topeltsize($1)!=4 with STACK kills ALL gen labeldef $1 - + pat bra topeltsize($1)==4 /* Unconditional jump with TOS GPRister */ with GPR3 STACK gen b {LABEL, $1} - + pat bra topeltsize($1)!=4 /* Unconditional jump without TOS GPRister */ with STACK gen b {LABEL, $1} - - - + + /* Miscellaneous */ pat cal /* Call procedure */ @@ -1848,23 +1898,23 @@ PATTERNS bl {LABEL, $1} pat cai /* Call procedure indirect */ - with GPR STACK + with REG STACK kills ALL gen mtspr CTR, %1 - bcctrl ALWAYS, {CONST, 0}, {CONST, 0} - + bctrl. + pat lfr $1==INT32 /* Load function result, word */ yields R3 - + pat lfr $1==INT64 /* Load function result, double-word */ yields R4 R3 - + pat ret $1==0 /* Return from procedure */ gen return b {LABEL, ".ret"} - + pat ret $1==INT32 /* Return from procedure, word */ with GPR3 gen @@ -1878,36 +1928,35 @@ PATTERNS b {LABEL, ".ret"} pat blm /* Block move constant length */ - with GPR GPR STACK + with REG REG STACK uses REG gen move {CONST, $1}, %a - stwu %a, {GPRINDIRECT, SP, 0-4} - stwu %2, {GPRINDIRECT, SP, 0-4} - stwu %1, {GPRINDIRECT, SP, 0-4} + stwu %a, {IND_RC_W, SP, 0-4} + stwu %2, {IND_RC_W, SP, 0-4} + stwu %1, {IND_RC_W, SP, 0-4} bl {LABEL, "_memmove"} addi SP, SP, {CONST, 12} - + pat bls /* Block move variable length */ - with GPR GPR GPR STACK + with REG REG REG STACK gen - stwu %1, {GPRINDIRECT, SP, 0-4} - stwu %3, {GPRINDIRECT, SP, 0-4} - stwu %2, {GPRINDIRECT, SP, 0-4} + stwu %1, {IND_RC_W, SP, 0-4} + stwu %3, {IND_RC_W, SP, 0-4} + stwu %2, {IND_RC_W, SP, 0-4} bl {LABEL, "_memmove"} addi SP, SP, {CONST, 12} - + pat csa /* Array-lookup switch */ with STACK gen b {LABEL, ".csa"} - + pat csb /* Table-lookup switch */ with STACK gen b {LABEL, ".csb"} - /* EM specials */ @@ -1915,7 +1964,7 @@ PATTERNS leaving lae $1 ste "hol0+4" - + pat lin /* Set current line number */ leaving loc $1 @@ -1924,53 +1973,53 @@ PATTERNS pat lni /* Increment line number */ leaving ine "hol0" - + pat lim /* Load EM trap ignore mask */ leaving lde ".ignmask" - + pat sim /* Store EM trap ignore mask */ leaving ste ".ignmask" - + pat trp /* Raise EM trap */ with GPR3 gen bl {LABEL, ".trap"} - + pat sig /* Set trap handler */ leaving ste ".trppc" - + pat rtt /* Return from trap */ leaving ret 0 - + pat lxl $1==0 /* Load FP */ leaving lor 0 - + pat lxl $1==1 /* Load caller's FP */ leaving lxl 0 dch - + pat dch /* FP -> caller FP */ - with GPR + with REG uses reusing %1, REG gen - lwz %a, {GPRINDIRECT, %1, FP_OFFSET} + lwz %a, {IND_RC_W, %1, FP_OFFSET} yields %a pat lpb /* Convert FP to argument address */ leaving adp EM_BSIZE - + pat lxa /* Load caller's SP */ leaving lxl $1 lpb - + pat gto /* longjmp */ uses REG gen @@ -1979,92 +2028,92 @@ PATTERNS move {IND_RC_W, %a, 4}, SP move {IND_RC_W, %a, 0}, %a mtspr CTR, %a - bcctr ALWAYS, {CONST, 0}, {CONST, 0} + bctr. pat lor $1==0 /* Load FP */ uses REG gen move FP, %a yields %a - + pat lor $1==1 /* Load SP */ uses REG gen move SP, %a yields %a - - pat lor $1==2 /* Load HP */ - leaving - loe ".reghp" - + pat str $1==0 /* Store FP */ - with GPR + with REG gen move %1, FP - + pat str $1==1 /* Store SP */ - with GPR + with REG gen move %1, SP - - pat str $1==2 /* Store HP */ - leaving - ste ".reghp" - pat loc ass $1==4 /* Drop 4 bytes from stack */ - with exact GPR + pat loc ass $1==4 && $2==4 /* Drop 4 bytes from stack */ + with exact REG /* nop */ with STACK gen addi SP, SP, {CONST, 4} - pat ass /* Adjust stack by variable amount */ + pat ass $1==4 /* Adjust stack by variable amount */ with CONST2 STACK gen move {SUM_RC, SP, %1.val}, SP with CONST_HZ STACK gen move {SUM_RC, SP, his(%1.val)}, SP - with CONST_ALL-CONST2-CONST_HZ STACK + with CONST_STACK-CONST2-CONST_HZ STACK gen move {SUM_RC, SP, his(%1.val)}, SP move {SUM_RC, SP, los(%1.val)}, SP - with GPR STACK + with REG STACK gen move {SUM_RR, SP, %1}, SP - + pat asp /* Adjust stack by constant amount */ leaving loc $1 - ass - - - + ass 4 + + pat lae rck $2==4 /* Range check */ + with REG + gen + cmpwi %1, {CONST, rom($1, 1)} + blt {LABEL, ".trap_erange"} + cmpwi %1, {CONST, rom($1, 2)} + bgt {LABEL, ".trap_erange"} + yields %1 + + /* Floating point support */ /* All very cheap and nasty --- this needs to be properly integrated into * the code generator. ncg doesn't like having separate FPU registers. */ /* Single-precision */ - + pat zrf $1==INT32 /* Push zero */ leaving loe ".fs_00000000" - + pat adf $1==INT32 /* Add single */ with FSREG FSREG uses reusing %1, FSREG gen fadds %a, %2, %1 yields %a - + pat sbf $1==INT32 /* Subtract single */ with FSREG FSREG uses reusing %1, FSREG gen fsubs %a, %2, %1 yields %a - + pat mlf $1==INT32 /* Multiply single */ with FSREG FSREG uses reusing %1, FSREG @@ -2088,57 +2137,110 @@ PATTERNS pat cmf $1==INT32 /* Compare single */ with FSREG FSREG - yields {TRISTATE_FF, %2.1, %1.1} - + uses REG={COND_FS, %2, %1} + gen extlwi %a, %a, {CONST, 2}, {CONST, 0} + yields %a + + pat cmf teq $1==4 /* Single second == top */ + with FSREG FSREG + uses REG={COND_FS, %2, %1} + gen move {XEQ, %a}, %a + yields %a + + pat cmf tne $1==4 /* Single second == top */ + with FSREG FSREG + uses REG={COND_FS, %2, %1} + gen move {XNE, %a}, %a + yields %a + + pat cmf tgt $1==4 /* Single second > top */ + with FSREG FSREG + uses REG={COND_FS, %2, %1} + gen move {XGT, %a}, %a + yields %a + + pat cmf tge $1==4 /* Single second >= top */ + with FSREG FSREG + uses REG={COND_FS, %2, %1} + gen move {XGE, %a}, %a + yields %a + + pat cmf tlt $1==4 /* Single second < top */ + with FSREG FSREG + uses REG={COND_FS, %2, %1} + gen move {XLT, %a}, %a + yields %a + + pat cmf tle $1==4 /* Single second <= top */ + with FSREG FSREG + uses REG={COND_FS, %2, %1} + gen move {XLE, %a}, %a + yields %a + + proc cmf4zxx example cmf zeq + with FREG FREG STACK + uses REG + gen + fcmpo CR0, %2, %1 + bxx* {LABEL, $2} + + /* Pop 2 singles, branch if... */ + pat cmf zeq $1==4 call cmf4zxx("beq") + pat cmf zne $1==4 call cmf4zxx("bne") + pat cmf zgt $1==4 call cmf4zxx("bgt") + pat cmf zge $1==4 call cmf4zxx("bge") + pat cmf zlt $1==4 call cmf4zxx("blt") + pat cmf zle $1==4 call cmf4zxx("ble") + pat loc loc cff $1==INT32 && $2==INT64 /* Convert single to double */ with FSREG yields %1.1 - + pat loc loc cfu $1==INT32 && $2==INT32 /* Convert single to unsigned int */ with STACK gen bl {LABEL, ".cfu4"} - + pat loc loc cfi $1==INT32 && $2==INT32 /* Convert single to signed int */ with STACK gen bl {LABEL, ".cfi4"} - + pat loc loc cif $1==INT32 && $2==INT32 /* Convert integer to single */ with STACK gen bl {LABEL, ".cif4"} - + pat loc loc cuf $1==INT32 && $2==INT32 /* Convert unsigned int to single */ with STACK gen bl {LABEL, ".cuf4"} - + pat fef $1==INT32 /* Split single */ with STACK gen bl {LABEL, ".fef4"} - + /* Double-precision */ - + pat zrf $1==INT64 /* Push zero */ leaving lde ".fd_00000000" - + pat adf $1==INT64 /* Add double */ with FREG FREG uses FREG gen fadd %a, %2, %1 yields %a - + pat sbf $1==INT64 /* Subtract double */ with FREG FREG uses FREG gen fsub %a, %2, %1 yields %a - + pat mlf $1==INT64 /* Multiply double */ with FREG FREG uses reusing %1, FREG @@ -2162,31 +2264,84 @@ PATTERNS pat cmf $1==INT64 /* Compare double */ with FREG FREG - yields {TRISTATE_FF, %2, %1} - + uses REG={COND_FD, %2, %1} + gen extlwi %a, %a, {CONST, 2}, {CONST, 0} + yields %a + + pat cmf teq $1==8 /* Double second == top */ + with FREG FREG + uses REG={COND_FD, %2, %1} + gen move {XEQ, %a}, %a + yields %a + + pat cmf tne $1==8 /* Single second == top */ + with FREG FREG + uses REG={COND_FD, %2, %1} + gen move {XNE, %a}, %a + yields %a + + pat cmf tgt $1==8 /* Double second > top */ + with FREG FREG + uses REG={COND_FD, %2, %1} + gen move {XGT, %a}, %a + yields %a + + pat cmf tge $1==8 /* Double second >= top */ + with FREG FREG + uses REG={COND_FD, %2, %1} + gen move {XGE, %a}, %a + yields %a + + pat cmf tlt $1==8 /* Double second < top */ + with FREG FREG + uses REG={COND_FD, %2, %1} + gen move {XLT, %a}, %a + yields %a + + pat cmf tle $1==8 /* Double second <= top */ + with FREG FREG + uses REG={COND_FD, %2, %1} + gen move {XLE, %a}, %a + yields %a + + proc cmf8zxx example cmf zeq + with FREG FREG STACK + uses REG + gen + fcmpo CR0, %2, %1 + bxx* {LABEL, $2} + + /* Pop 2 doubles, branch if... */ + pat cmf zeq $1==8 call cmf8zxx("beq") + pat cmf zne $1==8 call cmf8zxx("bne") + pat cmf zgt $1==8 call cmf8zxx("bgt") + pat cmf zge $1==8 call cmf8zxx("bge") + pat cmf zlt $1==8 call cmf8zxx("blt") + pat cmf zle $1==8 call cmf8zxx("ble") + pat loc loc cff $1==INT64 && $2==INT32 /* Convert double to single */ with FREG uses reusing %1, FSREG gen frsp %a, %1 yields %a - + pat loc loc cfu $1==INT64 && $2==INT32 /* Convert double to unsigned int */ with STACK gen bl {LABEL, ".cfu8"} - + pat loc loc cfi $1==INT64 && $2==INT32 /* Convert double to signed int */ with STACK gen bl {LABEL, ".cfi8"} - + pat loc loc cif $1==INT32 && $2==INT64 /* Convert integer to double */ with STACK kills ALL gen bl {LABEL, ".cif8"} - + pat loc loc cuf $1==INT32 && $2==INT64 /* Convert unsigned int to double */ with STACK gen @@ -2194,14 +2349,14 @@ PATTERNS pat fef $1==INT64 /* Split exponent, fraction */ with GPR3 GPR4 - kills FPR0, FPR1, GPR6, GPR7 + kills ALL gen bl {LABEL, ".fef8"} yields R4 R3 R5 pat fif $1==INT64 /* Multiply then split integer, fraction */ with FPR1 FPR2 - kills FPR1, FPR2, GPR3, GPR4, GPR5, GPR6 + kills ALL gen bl {LABEL, ".fif8"} yields F1 F2 diff --git a/mach/powerpc/top/table b/mach/powerpc/top/table index acbe543a7..fdec03b2e 100644 --- a/mach/powerpc/top/table +++ b/mach/powerpc/top/table @@ -6,15 +6,15 @@ LABEL_STARTER '.'; %%; -P, Q, R { TRUE }; +RNZ { strcmp(VAL, "r0") }; /* not r0 */ X, Y, Z { TRUE }; %%; /* Whitespace is significant here! */ -addi X, X, 0 -> ; -addis X, X, 0 -> ; +addi RNZ, RNZ, 0 -> ; +addis RNZ, RNZ, 0 -> ; mr X, X -> ; fmr X, X -> ; diff --git a/mach/proto/as/comm0.h b/mach/proto/as/comm0.h index dedafa4c7..2d00c8e45 100644 --- a/mach/proto/as/comm0.h +++ b/mach/proto/as/comm0.h @@ -8,7 +8,21 @@ * All preprocessor based options/constants/functions */ -#include +#ifdef _include +_include +_include +_include +_include +_include +_include +#else +#include +#include +#include +#include +#include +#include +#endif /* ========== ON/OFF options (use #define in mach0.c) ========== */ @@ -80,23 +94,16 @@ separate linker only possible if relocation info produced /* ========== Machine independent type declarations ========== */ #ifdef _include -_include -_include -_include -_include -_include -#else -#include -#include -#include -#include -#include +#ifdef ASLD +_include "arch.h" #endif - +_include "out.h" +#else #ifdef ASLD #include "arch.h" #endif #include "out.h" +#endif #if DEBUG == 0 #define assert(ex) /* nothing */ @@ -265,6 +272,3 @@ typedef struct sect_t sect_t; #define MACHREL_BWR (0) #endif #endif - -extern FILE *fopen(); /* some systems don't have this in stdio.h */ - diff --git a/mach/proto/as/comm1.h b/mach/proto/as/comm1.h index 6a40a2e90..b3011ac97 100644 --- a/mach/proto/as/comm1.h +++ b/mach/proto/as/comm1.h @@ -104,21 +104,28 @@ extern struct outhead outhead; extern int curr_token; /* forward function declarations */ +/* comm5.c */ +int yylex(void); +void putval(int); +int getval(int); +int nextchar(void); #ifdef ASLD -extern char *readident(); +char *readident(int); #endif -extern char *remember(); -extern item_t *fb_shift(); -extern item_t *fb_alloc(); -extern item_t *item_alloc(); -extern item_t *item_search(); -extern valu_t load(); -extern FILE *ffcreat(); -extern FILE *fftemp(); - -extern void fatal(const char* s, ...); -extern void serror(const char* s, ...); -extern void warning(const char* s, ...); +int hash(char *); +item_t *item_search(char *); +void item_insert(item_t *, int); +item_t *item_alloc(int); +item_t *fb_alloc(int); +item_t *fb_shift(int); +/* comm7.c */ +valu_t load(); +char *remember(); +FILE *ffcreat(); +FILE *fftemp(); +void fatal(const char *, ...); +void serror(const char *, ...); +void warning(const char *, ...); /* ========== Machine dependent C declarations ========== */ diff --git a/mach/proto/as/comm5.c b/mach/proto/as/comm5.c index 7dee7c1a9..1fa84537d 100644 --- a/mach/proto/as/comm5.c +++ b/mach/proto/as/comm5.c @@ -11,11 +11,18 @@ extern YYSTYPE yylval; -void putval(); +static void readcode(int); +static int induo(int); +static int inident(int); +static int innumber(int); +static int instring(int); +static int inescape(void); +static int infbsym(char *); -yylex() +int +yylex(void) { - register c; + int c, c0, c1; if (pass == PASS_1) { /* scan the input file */ @@ -52,32 +59,37 @@ yylex() /* produce the intermediate token file */ if (c <= 0) return(0); - if (c <= 127) + if (c < 256) { putc(c, tempfile); - else + putc(0, tempfile); + } else { putval(c); + } } else { /* read from intermediate token file */ - c = getc(tempfile); - if (c == EOF) + c0 = getc(tempfile); + if (c0 == EOF) return(0); - if (c > 127) { - c += 128; + c1 = getc(tempfile); + if (c1 == EOF) + return(0); + + c = c0 + (c1 << 8); + if (c >= 256) c = getval(c); - } } curr_token = c; return(c); } void -putval(c) +putval(int c) { register valu_t v; register n = 0; register char *p = 0; - assert(c >= 256 && c < 256+128); + assert(c == (c & 0xffff)); switch (c) { case CODE1: n = 1; goto putnum; @@ -92,9 +104,11 @@ putval(c) break; v >>= 8; } + assert(n <= 4); c = NUMBER0 + n; putnum: - putc(c-128, tempfile); + putc(c, tempfile); + putc(c >> 8, tempfile); v = yylval.y_valu; while (--n >= 0) putc((int) (v >> (n*8)), tempfile); @@ -110,14 +124,15 @@ putval(c) #endif case STRING: v = stringlen; - putc(c-128, tempfile); + putc(c, tempfile); + putc(c >> 8, tempfile); for (n = 0; n < sizeof(v); n++) { if (v == 0) break; v >>= 8; } - c = NUMBER0 + n; - putc(c-128, tempfile); + assert(n <= 4); + putc(n, tempfile); v = stringlen; while (--n >= 0) putc((int) (v >> (n*8)), tempfile); @@ -139,12 +154,14 @@ putval(c) n = sizeof(word_t); p = (char *) &yylval.y_word; break; } - putc(c-128, tempfile); + putc(c, tempfile); + putc(c >> 8, tempfile); while (--n >= 0) putc(*p++, tempfile); } -getval(c) +int +getval(int c) { register n = 0; register valu_t v; @@ -185,7 +202,7 @@ getval(c) p = (char *) &yylval.y_strp; break; #endif case STRING: - getval(getc(tempfile)+128); + getval(getc(tempfile)+NUMBER0); stringlen = n = yylval.y_valu; p = stringbuf; p[n] = '\0'; break; @@ -209,7 +226,8 @@ getval(c) /* ---------- lexical scan in pass 1 ---------- */ -nextchar() +int +nextchar(void) { register c; @@ -233,7 +251,8 @@ nextchar() return(c); } -readcode(n) +static void +readcode(int n) { register c; @@ -252,8 +271,8 @@ readcode(n) } while (--n); } -induo(c) -register c; +static int +induo(int c) { static short duo[] = { ('='<<8) | '=', OP_EQ, @@ -277,8 +296,8 @@ register c; static char name[NAMEMAX+1]; -inident(c) -register c; +static int +inident(int c) { register char *p = name; register item_t *ip; @@ -309,8 +328,7 @@ register c; #ifdef ASLD char * -readident(c) -register c; +readident(int c) { register n = NAMEMAX; register char *p = name; @@ -326,8 +344,8 @@ register c; } #endif -innumber(c) -register c; +static int +innumber(int c) { register char *p; register radix; @@ -373,7 +391,8 @@ register c; return(NUMBER); } -instring(termc) +static int +instring(int termc) { register char *p; register c; @@ -412,7 +431,8 @@ instring(termc) return(STRING); } -inescape() +static int +inescape(void) { register c, j, r; @@ -442,8 +462,8 @@ inescape() return(c); } -infbsym(p) -register char *p; +static int +infbsym(char *p) { register lab; register item_t *ip; @@ -469,8 +489,8 @@ ok: return(FBSYM); } -hash(p) -register char *p; +int +hash(char *p) { register unsigned short h; register c; @@ -484,8 +504,7 @@ register char *p; } item_t * -item_search(p) -char *p; +item_search(char *p) { register h; register item_t *ip; @@ -503,15 +522,15 @@ done: return(ip); } -item_insert(ip, h) -item_t *ip; +void +item_insert(item_t *ip, int h) { ip->i_next = hashtab[h]; hashtab[h] = ip; } item_t * -item_alloc(typ) +item_alloc(int typ) { register item_t *ip; static nleft = 0; @@ -532,8 +551,7 @@ item_alloc(typ) } item_t * -fb_alloc(lab) -register lab; +fb_alloc(int lab) { register item_t *ip, *p; @@ -548,8 +566,7 @@ register lab; } item_t * -fb_shift(lab) -register lab; +fb_shift(int lab) { register item_t *ip; diff --git a/mach/proto/as/comm6.c b/mach/proto/as/comm6.c index 9cb943cba..fdbeb77ff 100644 --- a/mach/proto/as/comm6.c +++ b/mach/proto/as/comm6.c @@ -354,8 +354,6 @@ valu_t valu; outname.on_type = type; outname.on_desc = desc; outname.on_valu = valu; - if (sizeof(valu) != sizeof(long)) - outname.on_valu &= ~(((0xFFFFFFFF)<<(4*sizeof(valu_t)))<<(4*sizeof(valu_t))); wr_name(&outname, 1); } diff --git a/mach/proto/mcg/data.c b/mach/proto/mcg/data.c index 13352ed37..ff4ddb5bd 100644 --- a/mach/proto/mcg/data.c +++ b/mach/proto/mcg/data.c @@ -12,14 +12,19 @@ static struct symbol* pending; void data_label(const char* label) { - if (pending) - fatal("two consecutive data labels ('%s' and '%s')", - pending->name, label); + struct symbol* sym = symbol_get(label); + if (sym->is_defined) + fatal("label '%s' defined twice", sym->name); - pending = symbol_get(label); - if (pending->is_defined) - fatal("label '%s' defined twice", pending->name); - pending->is_defined = true; + if (pending) + fprintf(outputfile, "%s = %s\n", + platform_label(label), platform_label(pending->name)); + else + { + pending = sym; + pending = symbol_get(label); + pending->is_defined = true; + } } static const char* section_to_str(int section) diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index 2ead527fc..eed770170 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -30,6 +30,18 @@ static void push(struct ir* ir) stack[stackptr++] = ir; } +/* Returns the size of the top item on the stack. */ +static int peek(int delta) +{ + if (stackptr <= delta) + return EM_wordsize; + else + { + struct ir* ir = stack[stackptr-1-delta]; + return ir->size; + } +} + static struct ir* pop(int size) { if (size < EM_wordsize) @@ -54,11 +66,10 @@ static struct ir* pop(int size) #if 0 /* If we try to pop something which is smaller than a word, convert it first. */ - + if (size < EM_wordsize) ir = convertu(ir, size); #endif - if (ir->size != size) { if ((size == (EM_wordsize*2)) && (ir->size == EM_wordsize)) @@ -119,6 +130,25 @@ static struct ir* appendir(struct ir* ir) return ir; } +static void sequence_point(void) +{ + int i; + + /* Ensures that any partially-evaluated expressions on the stack are executed right + * now. This typically needs to happen before store operations, to prevents loads of + * the same address being delayed until after the store (at which point they'll + * return incorrect values). + */ + + assert(current_bb != NULL); + + for (i=0; iirs, ir); + } +} + static void materialise_stack(void) { int i; @@ -170,7 +200,7 @@ static struct ir* address_of_external(const char* label, arith offset) static struct ir* convert(struct ir* src, int srcsize, int destsize, int opcode) { - if (srcsize == 1) + if (srcsize == 1) { if ((opcode == IR_FROMSI) || (opcode == IR_FROMSL)) { @@ -229,6 +259,8 @@ static struct ir* store(int size, struct ir* address, int offset, struct ir* val { int opcode; + sequence_point(); + if (size == 1) { opcode = IR_STOREB; @@ -401,7 +433,7 @@ static void insn_simple(int opcode) ); break; } - + case op_cii: simple_convert(IR_FROMSI); break; case op_ciu: simple_convert(IR_FROMSI); break; case op_cui: simple_convert(IR_FROMUI); break; @@ -475,6 +507,7 @@ static void insn_simple(int opcode) case op_sim: { + sequence_point(); appendir( new_ir2( (EM_wordsize == 2) ? IR_STORE : IR_STOREH, EM_wordsize, @@ -486,7 +519,19 @@ static void insn_simple(int opcode) } case op_trp: helper_function(".trp"); break; - case op_sig: helper_function(".sig"); break; + + case op_sig: + { + struct ir* value = pop(EM_pointersize); + appendir( + store( + EM_pointersize, + new_labelir(".trppc"), 0, + value + ) + ); + break; + } case op_rtt: { @@ -495,10 +540,12 @@ static void insn_simple(int opcode) } /* FIXME: These instructions are really complex and barely used - * (Modula-2 bitset support, I believe). Leave them until later. */ + * (Modula-2 and Pascal set support, I believe). Leave them until + * later. */ case op_set: helper_function(".unimplemented_set"); break; case op_ior: helper_function(".unimplemented_ior"); break; + case op_dch: push( new_ir1( @@ -507,7 +554,7 @@ static void insn_simple(int opcode) ) ); break; - + case op_lpb: push( new_ir1( @@ -574,29 +621,53 @@ static void insn_bvalue(int opcode, struct basicblock* leftbb, struct basicblock } } -static void simple_alu1(int opcode, int size, int irop) +static void simple_alu1(int opcode, int size, int irop, const char* fallback) { - struct ir* val = pop(size); + if (size > (2*EM_wordsize)) + { + if (!fallback) + fatal("treebuilder: can't do opcode %s with size %d", em_mnem[opcode - sp_fmnem], size); + push( + new_wordir(size) + ); + helper_function(fallback); + } + else + { + struct ir* val = pop(size); - push( - new_ir1( - irop, size, - val - ) - ); + push( + new_ir1( + irop, size, + val + ) + ); + } } -static void simple_alu2(int opcode, int size, int irop) +static void simple_alu2(int opcode, int size, int irop, const char* fallback) { - struct ir* right = pop(size); - struct ir* left = pop(size); + if (size > (2*EM_wordsize)) + { + if (!fallback) + fatal("treebuilder: can't do opcode %s with size %d", em_mnem[opcode - sp_fmnem], size); + push( + new_wordir(size) + ); + helper_function(fallback); + } + else + { + struct ir* right = pop(size); + struct ir* left = pop(size); - push( - new_ir2( - irop, size, - left, right - ) - ); + push( + new_ir2( + irop, size, + left, right + ) + ); + } } static struct ir* extract_block_refs(struct basicblock* bb) @@ -675,39 +746,43 @@ static void insn_ivalue(int opcode, arith value) { switch (opcode) { - case op_adi: simple_alu2(opcode, value, IR_ADD); break; - case op_sbi: simple_alu2(opcode, value, IR_SUB); break; - case op_mli: simple_alu2(opcode, value, IR_MUL); break; - case op_dvi: simple_alu2(opcode, value, IR_DIV); break; - case op_rmi: simple_alu2(opcode, value, IR_MOD); break; - case op_sli: simple_alu2(opcode, value, IR_ASL); break; - case op_sri: simple_alu2(opcode, value, IR_ASR); break; - case op_ngi: simple_alu1(opcode, value, IR_NEG); break; + case op_adi: simple_alu2(opcode, value, IR_ADD, NULL); break; + case op_sbi: simple_alu2(opcode, value, IR_SUB, NULL); break; + case op_mli: simple_alu2(opcode, value, IR_MUL, NULL); break; + case op_dvi: simple_alu2(opcode, value, IR_DIV, NULL); break; + case op_rmi: simple_alu2(opcode, value, IR_MOD, NULL); break; + case op_sli: simple_alu2(opcode, value, IR_ASL, NULL); break; + case op_sri: simple_alu2(opcode, value, IR_ASR, NULL); break; + case op_ngi: simple_alu1(opcode, value, IR_NEG, NULL); break; - case op_adu: simple_alu2(opcode, value, IR_ADD); break; - case op_sbu: simple_alu2(opcode, value, IR_SUB); break; - case op_mlu: simple_alu2(opcode, value, IR_MUL); break; - case op_slu: simple_alu2(opcode, value, IR_LSL); break; - case op_sru: simple_alu2(opcode, value, IR_LSR); break; - case op_rmu: simple_alu2(opcode, value, IR_MODU); break; - case op_dvu: simple_alu2(opcode, value, IR_DIVU); break; + case op_adu: simple_alu2(opcode, value, IR_ADD, NULL); break; + case op_sbu: simple_alu2(opcode, value, IR_SUB, NULL); break; + case op_mlu: simple_alu2(opcode, value, IR_MUL, NULL); break; + case op_slu: simple_alu2(opcode, value, IR_LSL, NULL); break; + case op_sru: simple_alu2(opcode, value, IR_LSR, NULL); break; + case op_rmu: simple_alu2(opcode, value, IR_MODU, NULL); break; + case op_dvu: simple_alu2(opcode, value, IR_DIVU, NULL); break; - case op_and: simple_alu2(opcode, value, IR_AND); break; - case op_ior: simple_alu2(opcode, value, IR_OR); break; - case op_xor: simple_alu2(opcode, value, IR_EOR); break; - case op_com: simple_alu1(opcode, value, IR_NOT); break; + case op_and: simple_alu2(opcode, value, IR_AND, ".and"); break; + case op_ior: simple_alu2(opcode, value, IR_OR, ".ior"); break; + case op_xor: simple_alu2(opcode, value, IR_EOR, NULL); break; + case op_com: simple_alu1(opcode, value, IR_NOT, ".com"); break; - case op_adf: simple_alu2(opcode, value, IR_ADDF); break; - case op_sbf: simple_alu2(opcode, value, IR_SUBF); break; - case op_mlf: simple_alu2(opcode, value, IR_MULF); break; - case op_dvf: simple_alu2(opcode, value, IR_DIVF); break; - case op_ngf: simple_alu1(opcode, value, IR_NEGF); break; + case op_adf: simple_alu2(opcode, value, IR_ADDF, NULL); break; + case op_sbf: simple_alu2(opcode, value, IR_SUBF, NULL); break; + case op_mlf: simple_alu2(opcode, value, IR_MULF, NULL); break; + case op_dvf: simple_alu2(opcode, value, IR_DIVF, NULL); break; + case op_ngf: simple_alu1(opcode, value, IR_NEGF, NULL); break; case op_cmu: /* fall through */ case op_cms: push(tristate_compare(value, IR_COMPAREUI)); break; case op_cmi: push(tristate_compare(value, IR_COMPARESI)); break; case op_cmf: push(tristate_compare(value, IR_COMPAREF)); break; + case op_rck: helper_function(".rck"); break; + case op_set: push(new_wordir(value)); helper_function(".set"); break; + case op_inn: push(new_wordir(value)); helper_function(".inn"); break; + case op_lol: push( load( @@ -841,7 +916,7 @@ static void insn_ivalue(int opcode, arith value) ) ); break; - + case op_loc: push( new_wordir(value) @@ -853,17 +928,17 @@ static void insn_ivalue(int opcode, arith value) struct ir* ptr = pop(EM_pointersize); int offset = 0; - /* FIXME: this is awful; need a better way of dealing with - * non-standard EM sizes. */ if (value > (EM_wordsize*2)) + { + /* We're going to need to do multiple stores; fix the address + * so it'll go into a register and we can do maths on it. */ appendir(ptr); + } while (value > 0) { - int s; - if (value > (EM_wordsize*2)) - s = EM_wordsize*2; - else + int s = EM_wordsize*2; + if (value < s) s = value; push( @@ -912,24 +987,25 @@ static void insn_ivalue(int opcode, arith value) struct ir* ptr = pop(EM_pointersize); int offset = 0; - /* FIXME: this is awful; need a better way of dealing with - * non-standard EM sizes. */ - if (value > (EM_wordsize*2)) + if (value > peek(0)) + { + /* We're going to need to do multiple stores; fix the address + * so it'll go into a register and we can do maths on it. */ appendir(ptr); + } while (value > 0) { - int s; - if (value > (EM_wordsize*2)) - s = EM_wordsize*2; - else + struct ir* v = pop(peek(0)); + int s = v->size; + if (value < s) s = value; appendir( store( s, ptr, offset, - pop(s) + v ) ); @@ -1007,7 +1083,7 @@ static void insn_ivalue(int opcode, arith value) struct ir* right = pop(EM_pointersize); struct ir* left = pop(EM_pointersize); - struct ir* delta = + struct ir* delta = new_ir2( IR_SUB, EM_pointersize, left, right @@ -1019,13 +1095,25 @@ static void insn_ivalue(int opcode, arith value) push(delta); break; } - + case op_dup: { - struct ir* v = pop(value); - appendir(v); - push(v); - push(v); + sequence_point(); + if ((value == (EM_wordsize*2)) && (peek(0) == EM_wordsize) && (peek(1) == EM_wordsize)) + { + struct ir* v1 = pop(EM_wordsize); + struct ir* v2 = pop(EM_wordsize); + push(v2); + push(v1); + push(v2); + push(v1); + } + else + { + struct ir* v = pop(value); + push(v); + push(v); + } break; } @@ -1038,6 +1126,18 @@ static void insn_ivalue(int opcode, arith value) break; } + case op_zer: + { + if (value <= EM_wordsize) + push(new_constir(value, 0)); + else + { + push(new_wordir(value)); + helper_function(".zer"); + } + break; + } + case op_asp: { switch (value) @@ -1055,19 +1155,19 @@ static void insn_ivalue(int opcode, arith value) default: while ((value > 0) && (stackptr > 0)) { - struct ir* ir = pop(stack[stackptr-1]->size); - value -= ir->size; + int s = peek(0); + if (s > value) + s = value; + pop(s); + value -= s; } - if (value != 0) - { - appendir( - new_ir1( - IR_STACKADJUST, EM_pointersize, - new_wordir(value) - ) - ); - } + appendir( + new_ir1( + IR_STACKADJUST, EM_pointersize, + new_wordir(value) + ) + ); break; } break; @@ -1120,7 +1220,7 @@ static void insn_ivalue(int opcode, arith value) ); break; } - + case op_lfr: { push( @@ -1251,11 +1351,11 @@ static void insn_ivalue(int opcode, arith value) new_labelir((value == 4) ? ".fef4" : ".fef8") ) ); - + /* exit, leaving an int and then a float (or double) on the stack. */ break; } - + case op_fif: { /* fif is implemented by calling a helper function which then mutates @@ -1271,11 +1371,11 @@ static void insn_ivalue(int opcode, arith value) new_labelir((value == 4) ? ".fif4" : ".fif8") ) ); - + /* exit, leaving two floats (or doubles) on the stack. */ break; } - + case op_lor: { switch (value) @@ -1292,7 +1392,7 @@ static void insn_ivalue(int opcode, arith value) ) ); break; - + case 1: push( appendir( @@ -1443,18 +1543,6 @@ static void insn_ivalue(int opcode, arith value) break; } - /* FIXME: These instructions are really complex and barely used - * (Modula-2 bitset support, I believe). Leave them until leter. */ - case op_inn: - { - push( - new_wordir(value) - ); - - helper_function(".inn"); - break; - } - case op_lin: { /* Set line number --- ignore. */ @@ -1497,6 +1585,7 @@ static void insn_lvalue(int opcode, const char* label, arith offset) break; case op_ste: + sequence_point(); appendir( new_ir2( IR_STORE, EM_wordsize, @@ -1507,6 +1596,7 @@ static void insn_lvalue(int opcode, const char* label, arith offset) break; case op_sde: + sequence_point(); appendir( new_ir2( IR_STORE, EM_wordsize*2, @@ -1517,6 +1607,7 @@ static void insn_lvalue(int opcode, const char* label, arith offset) break; case op_zre: + sequence_point(); appendir( new_ir2( IR_STORE, EM_wordsize, @@ -1525,8 +1616,9 @@ static void insn_lvalue(int opcode, const char* label, arith offset) ) ); break; - + case op_ine: + sequence_point(); appendir( new_ir2( IR_STORE, EM_wordsize, @@ -1544,6 +1636,7 @@ static void insn_lvalue(int opcode, const char* label, arith offset) break; case op_dee: + sequence_point(); appendir( new_ir2( IR_STORE, EM_wordsize, @@ -1612,7 +1705,7 @@ static void insn_lvalue(int opcode, const char* label, arith offset) /* Set filename --- ignore. */ break; } - + default: fatal("treebuilder: unknown lvalue instruction '%s'", em_mnem[opcode - sp_fmnem]); @@ -1645,7 +1738,7 @@ static void generate_tree(struct basicblock* bb) break; case PARAM_LVALUE: - tracef('E', "label=%s offset=%d\n", + tracef('E', "label=%s offset=%d\n", em->u.lvalue.label, em->u.lvalue.offset); insn_lvalue(em->opcode, em->u.lvalue.label, em->u.lvalue.offset); break; diff --git a/mach/proto/ncg/codegen.c b/mach/proto/ncg/codegen.c index 15d99d393..95a3c012d 100644 --- a/mach/proto/ncg/codegen.c +++ b/mach/proto/ncg/codegen.c @@ -22,12 +22,12 @@ static char rcsid[] = "$Id$"; * Author: Hans van Staveren */ -#define ALLOW_NEXTEM /* code generator is allowed new try of NEXTEM - in exceptional cases */ +#define ALLOW_NEXTEM /* code generator is allowed new try of NEXTEM \ + in exceptional cases */ byte startupcode[] = { DO_NEXTEM }; -byte *nextem(); +byte* nextem(); unsigned costcalc(); unsigned docoerc(); unsigned stackupto(); @@ -38,885 +38,1046 @@ string ad2str(); #define DEBUG(string) #else #include -#define DEBUG(string) {if(Debug) fprintf(stderr,"%-*d%s\n",4*level,level,string);} +#define DEBUG(string) \ + { \ + if (Debug) \ + fprintf(stderr, "%-*d%s\n", 4 * level, level, string); \ + } #endif -#define BROKE() {assert(origcp!=startupcode || !paniced);DEBUG("BROKE");totalcost=INFINITY;goto doreturn;} -#define CHKCOST() {if (totalcost>=costlimit) BROKE();} +#define BROKE() \ + { \ + assert(origcp != startupcode || !paniced); \ + DEBUG("BROKE"); \ + totalcost = INFINITY; \ + goto doreturn; \ + } +#define CHKCOST() \ + { \ + if (totalcost >= costlimit) \ + BROKE(); \ + } #ifdef TABLEDEBUG int tablelines[MAXTDBUG]; int ntableline; -int set_fd,set_size; -short *set_val; -char *set_flag; +int set_fd, set_size; +short* set_val; +char* set_flag; #endif -unsigned codegen(codep,ply,toplevel,costlimit,forced) byte *codep; unsigned costlimit; { +unsigned codegen(byte* codep, int ply, int toplevel, unsigned costlimit, int forced) +{ #ifndef NDEBUG - byte *origcp=codep; - static int level=0; + byte* origcp = codep; + static int level = 0; #endif unsigned totalcost = 0; - int inscoerc=0; - int procarg[MAXPROCARG+1]; + int inscoerc = 0; + int procarg[MAXPROCARG + 1] = {}; #ifdef ALLOW_NEXTEM static int paniced; - char *savebp = 0; + char* savebp = 0; #endif state_t state; -#define SAVEST savestatus(&state) -#define RESTST restorestatus(&state) -#define FREEST /* nothing */ +#define SAVEST savestatus(&state) +#define RESTST restorestatus(&state) +#define FREEST /* nothing */ #ifdef TABLEDEBUG - extern char *tablename; + extern char* tablename; #endif #ifndef NDEBUG assert(costlimit <= INFINITY); level++; DEBUG("Entering codegen"); - if (Debug > 1) fprintf(stderr, "toplevel = %d\n", toplevel); + if (Debug > 1) + fprintf(stderr, "toplevel = %d\n", toplevel); #endif - for (;;) { - switch( (*codep++)&037 ) { - default: - assert(FALSE); - /* NOTREACHED */ + for (;;) + { + switch ((*codep++) & 037) + { + default: + assert(FALSE); +/* NOTREACHED */ #ifdef TABLEDEBUG - case DO_DLINE: { - int n; + case DO_DLINE: + { + int n; - getint(n,codep); - tablelines[ntableline++] = n; - if (ntableline>=MAXTDBUG) - ntableline -= MAXTDBUG; - if (set_fd) - set_val[n>>4] &= ~(1<<(n&017)); + getint(n, codep); + tablelines[ntableline++] = n; + if (ntableline >= MAXTDBUG) + ntableline -= MAXTDBUG; + if (set_fd) + set_val[n >> 4] &= ~(1 << (n & 017)); #ifndef NDEBUG - if (Debug) - fprintf(stderr,"code from \"%s\", line %d\n",tablename,n); + if (Debug) + fprintf(stderr, "code from \"%s\", line %d\n", tablename, n); #endif - break; - } + break; + } #endif - case DO_NEXTEM: { - byte *bp; - int n; - unsigned mindistance,dist; - register i; - int cindex; - int npos,pos[MAXRULE]; - unsigned mincost,t; + case DO_NEXTEM: + { + byte* bp; + int n; + unsigned mindistance, dist; + register i; + int cindex; + int npos, pos[MAXRULE]; + unsigned mincost, t; - DEBUG("NEXTEM"); - tokpatlen = 0; - nallreg=0; - if (toplevel) { - garbage_collect(); - totalcost=0; - } else { - if (--ply <= 0) - goto doreturn; - } - if (stackheight>MAXFSTACK-7) { + DEBUG("NEXTEM"); + tokpatlen = 0; + nallreg = 0; + if (toplevel) + { + garbage_collect(); + totalcost = 0; + } + else + { + if (--ply <= 0) + goto doreturn; + } + if (stackheight > MAXFSTACK - 7) + { #ifndef NDEBUG - if (Debug) - fprintf(stderr,"Fakestack overflow threatens(%d), action ...\n",stackheight); + if (Debug) + fprintf(stderr, "Fakestack overflow threatens(%d), action ...\n", stackheight); #endif - totalcost += stackupto(&fakestack[6],ply,toplevel); - } + totalcost += stackupto(&fakestack[6], ply, toplevel); + } #ifndef ALLOW_NEXTEM - bp = nextem(toplevel); + bp = nextem(toplevel); #else - if (toplevel) paniced=0; - savebp = nextem(toplevel); - panic: - if (toplevel) totalcost = 0; - bp = savebp; + if (toplevel) + paniced = 0; + savebp = nextem(toplevel); + panic: + if (toplevel) + totalcost = 0; + bp = savebp; #endif - if (bp == 0) { - /* + if (bp == 0) + { + /* * No pattern found, can be pseudo or error * in table. */ - if (toplevel) { - codep--; - DEBUG("pseudo"); - dopseudo(); - } else - goto doreturn; - } else { -#ifndef NDEBUG - chkregs(); -#endif - if (! toplevel) { - ply -= emp-saveemp+1; - if (ply <= 0) ply = 1; - } - n = *bp++; - if (n==0) { /* "procedure" */ - int j, nargs; - getint(i,bp); - getint(nargs,bp); - assert(nargs <= MAXPROCARG); - for (j = 0; j < nargs; j++) { - getint(procarg[j],bp); - } - bp= &pattern[i]; - n = *bp++; - DEBUG("PROC_CALL"); - } - assert(n>0 && n<=MAXRULE); - if (n>1) { - mindistance = MAXINT; npos=0; - for(i=0;i1) { - /* + else + { +#ifndef NDEBUG + chkregs(); +#endif + if (!toplevel) + { + ply -= emp - saveemp + 1; + if (ply <= 0) + ply = 1; + } + n = *bp++; + if (n == 0) + { /* "procedure" */ + int j, nargs; + getint(i, bp); + getint(nargs, bp); + assert(nargs <= MAXPROCARG); + for (j = 0; j < nargs; j++) + { + getint(procarg[j], bp); + } + bp = &pattern[i]; + n = *bp++; + DEBUG("PROC_CALL"); + } + assert(n > 0 && n <= MAXRULE); + if (n > 1) + { + mindistance = MAXINT; + npos = 0; + for (i = 0; i < n; i++) + { + getint(cindex, bp); + dist = distance(cindex); +#ifndef NDEBUG + if (Debug) + fprintf(stderr, "distance of pos %d is %u\n", i, dist); +#endif + if (dist <= mindistance +#ifdef ALLOW_NEXTEM + || paniced +#endif + ) + { + if (dist < mindistance) + { + if (dist == 0) + goto gotit; + npos = 0; + mindistance = dist; + } +#ifdef ALLOW_NEXTEM + if (dist < MAXINT) +#endif + pos[npos++] = cindex; + } + } + assert(mindistance < MAXINT); + if (npos > 1) + { + /* * More than 1 tokenpattern is a candidate. * Decision has to be made by lookahead. */ - SAVEST; - mincost = costlimit-totalcost+1; - assert(mincost <= INFINITY); - for(i=0;i costlimit) + { + BROKE(); + } + } + else + { + cindex = pos[0]; + } + } + else + { + getint(cindex, bp); } - RESTST; - } - FREEST; - if (totalcost+mincost>costlimit) { - BROKE(); - } - } else { - cindex = pos[0]; - } - } else { - getint(cindex,bp); - } - gotit: - /* + gotit: + /* * Now cindex contains the code-index of the best candidate * so proceed to use it. */ - codep = &coderules[cindex]; - } - break; - } - case DO_COERC: { - DEBUG("COERC"); - tokpatlen=1; - inscoerc=1; - break; - } - case DO_XXMATCH: - DEBUG("XXMATCH"); - case DO_XMATCH: { - register i; - int temp; - - DEBUG("XMATCH"); - tokpatlen=(codep[-1]>>5)&07; - for (i=0;i>5)&07; - for(i=0;i=fakestack) { - size=tsize(tp); - while (i= fakestack) { - size = tsize(tp); - lsize= ssize(tokexp[i]); - if (size != lsize) { /* find coercion */ -#ifdef MAXSPLIT - sret = split(tp,&tokexp[i],ply,toplevel); - if (sret==0) { -#endif /* MAXSPLIT */ - totalcost += stackupto(tp,ply,toplevel); - CHKCOST(); - break; -#ifdef MAXSPLIT - } - i += sret; -#endif /* MAXSPLIT */ - } else - i += 1; - tp--; - } - nextmatch: - tp = &fakestack[stackheight-1]; - i=0; nregneeded = 0; - while (i=fakestack) { - if (!match(tp,&machsets[tokexp[i]],0)) { - cp = findcoerc(tp, &machsets[tokexp[i]]); -#ifndef NDEBUG -if (Debug>1) fprintf(stderr,"findcoerc returns 0x%x at position %d\n",(unsigned)cp,i); -#endif - if (cp==0) { - for (j=0;jc3_prop<0) { - totalcost+=docoerc(tp,cp,ply,toplevel,0); - CHKCOST(); - } else { -#ifndef NDEBUG -if(Debug>1) fprintf(stderr,"Register of type %d needed, remembering...\n",cp->c3_prop); -#endif - assert(nregneededstackheight) { -#ifndef NDEBUG -if(Debug>1) fprintf(stderr,"Pattern too long, %d with only %d items on stack\n", - tokpatlen,stackheight); + case DO_COERC: + { + DEBUG("COERC"); + tokpatlen = 1; + inscoerc = 1; + break; + } + case DO_XXMATCH: + DEBUG("XXMATCH"); + case DO_XMATCH: + { + register i; + int temp; + + DEBUG("XMATCH"); + tokpatlen = (codep[-1] >> 5) & 07; + for (i = 0; i < tokpatlen; i++) + getint(temp, codep); + break; /* match already checked by distance() */ + } + case DO_MATCH: + { + register i; + int j; + unsigned mincost, t; + token_p tp; + int size, lsize; + int tokexp[MAXPATLEN]; + int nregneeded; + token_p regtp[MAXCREG]; + c3_p regcp[MAXCREG]; + rl_p regls[MAXCREG]; + c3_p cp, findcoerc(); +#ifdef MAXSPLIT + int sret; #endif - stackpad = tokpatlen-stackheight; - for (j=stackheight-1;j>=0;j--) - fakestack[j+stackpad] = fakestack[j]; - for (j=0;j=fakestack;i++,tp--) { - cp = findcoerc((token_p) 0, &machsets[tokexp[i]]); - if (cp==0) { - for (j=0;j> 5) & 07; + for (i = 0; i < tokpatlen; i++) + getint(tokexp[i], codep); + tp = &fakestack[stackheight - 1]; + i = 0; + while (i < tokpatlen && tp >= fakestack) + { + size = tsize(tp); + while (i < tokpatlen && (lsize = ssize(tokexp[i])) <= size) + { + size -= lsize; + i++; + } + if (i < tokpatlen && size != 0) + { + totalcost += stackupto(tp, ply, toplevel); + CHKCOST(); + break; + } + tp--; + } + tp = &fakestack[stackheight - 1]; + i = 0; + while (i < tokpatlen && tp >= fakestack) + { + size = tsize(tp); + lsize = ssize(tokexp[i]); + if (size != lsize) + { /* find coercion */ +#ifdef MAXSPLIT + sret = split(tp, &tokexp[i], ply, toplevel); + if (sret == 0) + { +#endif /* MAXSPLIT */ + totalcost += stackupto(tp, ply, toplevel); + CHKCOST(); + break; +#ifdef MAXSPLIT + } + i += sret; +#endif /* MAXSPLIT */ + } + else + i += 1; + tp--; + } + nextmatch: + tp = &fakestack[stackheight - 1]; + i = 0; + nregneeded = 0; + while (i < tokpatlen && tp >= fakestack) + { + if (!match(tp, &machsets[tokexp[i]], 0)) + { + cp = findcoerc(tp, &machsets[tokexp[i]]); +#ifndef NDEBUG + if (Debug > 1) + fprintf(stderr, "findcoerc returns 0x%x at position %d\n", (unsigned)cp, i); +#endif + if (cp == 0) + { + for (j = 0; j < nregneeded; j++) + regtp[j] -= (tp - fakestack + 1); + totalcost += stackupto(tp, ply, toplevel); + CHKCOST(); + break; + } + else + { + if (cp->c3_prop < 0) + { + totalcost += docoerc(tp, cp, ply, toplevel, 0); + CHKCOST(); + } + else + { +#ifndef NDEBUG + if (Debug > 1) + fprintf(stderr, "Register of type %d needed, remembering...\n", cp->c3_prop); +#endif + assert(nregneeded < MAXCREG); + regtp[nregneeded] = tp; + regcp[nregneeded] = cp; + regls[nregneeded] = curreglist; + nregneeded++; + } + } + } + i++; + tp--; + } + if (tokpatlen > stackheight) + { +#ifndef NDEBUG + if (Debug > 1) + fprintf(stderr, "Pattern too long, %d with only %d items on stack\n", + tokpatlen, stackheight); +#endif + stackpad = tokpatlen - stackheight; + for (j = stackheight - 1; j >= 0; j--) + fakestack[j + stackpad] = fakestack[j]; + for (j = 0; j < stackpad; j++) + fakestack[j].t_token = 0; + stackheight += stackpad; + for (j = 0; j < nregneeded; j++) + regtp[j] += stackpad; + for (tp = &fakestack[stackpad - 1]; i < tokpatlen && tp >= fakestack; i++, tp--) + { + cp = findcoerc((token_p)0, &machsets[tokexp[i]]); + if (cp == 0) + { + for (j = 0; j < nregneeded; j++) + myfree((string)(regls[j])); #ifndef ALLOW_NEXTEM - assert(!toplevel); - BROKE(); + assert(!toplevel); + BROKE(); #else - assert(!(toplevel&&paniced)); - if (paniced) goto normalfailed; - totalcost = INFINITY; - for (i=0;ic3_prop<0) { - totalcost+=docoerc(tp,cp,ply,toplevel,0); - CHKCOST(); - } else { - assert(nregneededc3_prop < 0) + { + totalcost += docoerc(tp, cp, ply, toplevel, 0); + CHKCOST(); + } + else + { + assert(nregneeded < MAXCREG); + regtp[nregneeded] = tp; + regcp[nregneeded] = cp; + regls[nregneeded] = curreglist; + nregneeded++; + } + } + } + else + stackpad = 0; + assert(i == tokpatlen); + if (nregneeded == 0) + break; + SAVEST; + mincost = costlimit - totalcost + 1; + tup = tuples(regls, nregneeded); + besttup = 0; + for (; tup != 0; tup = ntup) + { #ifndef NDEBUG -if(Debug>1) { fprintf(stderr,"Next tuple %d,%d,%d,%d\n", - tup->p_rar[0], - tup->p_rar[1], - tup->p_rar[2], - tup->p_rar[3]); - fprintf(stderr, "totalcost = %u, costlimit = %u, mincost = %u\n", - totalcost, costlimit, mincost); - } + if (Debug > 1) + { + fprintf(stderr, "Next tuple %d,%d,%d,%d\n", + tup->p_rar[0], + tup->p_rar[1], + tup->p_rar[2], + tup->p_rar[3]); + fprintf(stderr, "totalcost = %u, costlimit = %u, mincost = %u\n", + totalcost, costlimit, mincost); + } #endif - ntup = tup->p_next; - for (i=0,t=0;ip_rar[i]); + ntup = tup->p_next; + for (i = 0, t = 0; i < nregneeded && t < mincost; i++) + t += docoerc(regtp[i], regcp[i], ply, FALSE, tup->p_rar[i]); #ifndef NDEBUG -if (Debug > 1) fprintf(stderr, "cost after coercions: %u\n", t); + if (Debug > 1) + fprintf(stderr, "cost after coercions: %u\n", t); #endif - if ( t2) - fprintf(stderr,"Continuing match after coercions\n"); + if (Debug > 2) + fprintf(stderr, "Continuing match after coercions\n"); #endif - t += codegen(codep,ply,FALSE,mincostcostlimit) { - if (besttup) - myfree((string)besttup); -normalfailed: if (stackpad!=tokpatlen) { - if (stackpad) { - for (i=0;i costlimit) + { + if (besttup) + myfree((string)besttup); + normalfailed: + if (stackpad != tokpatlen) + { + if (stackpad) + { + for (i = 0; i < stackheight - stackpad; i++) + fakestack[i] = fakestack[i + stackpad]; + stackheight -= stackpad; + if (costlimit < MAXINT) + BROKE(); + totalcost += stackupto(&fakestack[stackheight - 1], ply, toplevel); + } + else + totalcost += stackupto(fakestack, ply, toplevel); + CHKCOST(); + goto nextmatch; + } + totalcost += mincost; + for (i = 0; i < stackheight - stackpad; i++) + fakestack[i] = fakestack[i + stackpad]; + stackheight -= stackpad; BROKE(); - totalcost += stackupto(&fakestack[stackheight-1],ply,toplevel); - } else - totalcost += stackupto(fakestack,ply,toplevel); - CHKCOST(); - goto nextmatch; - } - totalcost += mincost; - for (i=0;ip_rar[i]); - assert(totalcost <= costlimit); - myfree((string)besttup); - break; - } - case DO_TOSTACK: - case DO_REMOVE: { - int texpno,nodeno; - token_p tp; - struct reginfo *rp; - int doremove = (codep[-1] & 037) == DO_REMOVE; - extern int allsetno; + } + for (i = 0; i < nregneeded; i++) + totalcost += docoerc(regtp[i], regcp[i], ply, toplevel, besttup->p_rar[i]); + assert(totalcost <= costlimit); + myfree((string)besttup); + break; + } + case DO_TOSTACK: + case DO_REMOVE: + { + int texpno, nodeno; + token_p tp; + struct reginfo* rp; + int doremove = (codep[-1] & 037) == DO_REMOVE; + extern int allsetno; - DEBUG(doremove ? "REMOVE" : "TOSTACK"); - if (codep[-1]&32) { - getint(texpno,codep); - getint(nodeno,codep); - } else { - getint(texpno,codep); - nodeno=0; - } - if (texpno == allsetno) { - totalcost += stackupto(&fakestack[stackheight-tokpatlen-1],ply,toplevel); - CHKCOST(); - if (doremove) for (rp=machregs;rpr_contents.t_token=0; - break; - } - for (tp= &fakestack[stackheight-tokpatlen-1];tp>=&fakestack[0];tp--) - if (match(tp,&machsets[texpno],nodeno)) { - /* investigate possible coercion to register */ - totalcost += stackupto(tp,ply,toplevel); - CHKCOST(); - break; - } - if (doremove) for (rp=machregs;rpr_contents.t_token != 0 && - match(&rp->r_contents,&machsets[texpno],nodeno)) { + DEBUG(doremove ? "REMOVE" : "TOSTACK"); + if (codep[-1] & 32) + { + getint(texpno, codep); + getint(nodeno, codep); + } + else + { + getint(texpno, codep); + nodeno = 0; + } + if (texpno == allsetno) + { + totalcost += stackupto(&fakestack[stackheight - tokpatlen - 1], ply, toplevel); + CHKCOST(); + if (doremove) + for (rp = machregs; rp < machregs + NREGS; rp++) + rp->r_contents.t_token = 0; + break; + } + for (tp = &fakestack[stackheight - tokpatlen - 1]; tp >= &fakestack[0]; tp--) + if (match(tp, &machsets[texpno], nodeno)) + { + /* investigate possible coercion to register */ + totalcost += stackupto(tp, ply, toplevel); + CHKCOST(); + break; + } + if (doremove) + for (rp = machregs; rp < machregs + NREGS; rp++) + { + if (rp->r_contents.t_token != 0 && match(&rp->r_contents, &machsets[texpno], nodeno)) + { #ifndef NDEBUG - if (Debug > 1) fprintf(stderr, "killing reg %ld (%s)\n", (long)(rp-machregs), rp->r_repr ? codestrings[rp->r_repr] : "cc"); + if (Debug > 1) + fprintf(stderr, "killing reg %ld (%s)\n", (long)(rp - machregs), rp->r_repr ? codestrings[rp->r_repr] : "cc"); #endif - rp->r_contents.t_token=0; - } - } - break; - } - case DO_KILLREG: - case DO_RREMOVE: { /* register remove */ - register i; - int nodeno; - token_p tp; - tkdef_p tdp; - result_t result; - int dokill = (codep[-1] & 037) == DO_KILLREG; + rp->r_contents.t_token = 0; + } + } + break; + } + case DO_KILLREG: + case DO_RREMOVE: + { /* register remove */ + register i; + int nodeno; + token_p tp; + tkdef_p tdp; + result_t result; + int dokill = (codep[-1] & 037) == DO_KILLREG; - DEBUG(dokill ? "KILLREG" : "RREMOVE"); - getint(nodeno,codep); - compute(&enodes[nodeno], &result); - if (result.e_typ!=EV_REG) - break; - if ( in_stack(result.e_v.e_reg) ) BROKE() ; /* Check aside-stack */ - if (dokill) { - /* kill register, and kill condition codes if they are set to + DEBUG(dokill ? "KILLREG" : "RREMOVE"); + getint(nodeno, codep); + compute(&enodes[nodeno], &result); + if (result.e_typ != EV_REG) + break; + if (in_stack(result.e_v.e_reg)) + BROKE(); /* Check aside-stack */ + if (dokill) + { + /* kill register, and kill condition codes if they are set to this register */ - machregs[result.e_v.e_reg].r_contents.t_token = 0; - if (machregs[0].r_contents.t_token == -1 && - machregs[0].r_contents.t_att[0].ar == result.e_v.e_reg) { - machregs[0].r_contents.t_token = 0; - } - } - for (tp= &fakestack[stackheight-tokpatlen-1];tp>=&fakestack[0];tp--) - if (tp->t_token==-1) { - if(tp->t_att[0].ar==result.e_v.e_reg) - goto gotone; - } else { - tdp = &tokens[tp->t_token]; - for(i=0;it_type[i]==EV_REG && - tp->t_att[i].ar==result.e_v.e_reg) - goto gotone; - } - break; - gotone: - /* investigate possible coercion to register */ - totalcost += stackupto(tp,ply,toplevel); - CHKCOST(); - break; - } - case DO_DEALLOCATE: { - register i; - tkdef_p tdp; - int tinstno; - token_t token; - - DEBUG("DEALLOCATE"); - getint(tinstno,codep); - instance(tinstno,&token); - if (token.t_token==-1) - chrefcount(token.t_att[0].ar,-1,TRUE); - else { - tdp= &tokens[token.t_token]; - for (i=0;it_type[i]==EV_REG) - chrefcount(token.t_att[i].ar,-1,TRUE); - } - break; - } - case DO_REALLOCATE: { - struct reginfo *rp; - - DEBUG("REALLOCATE"); - for(rp=machregs+1;rpr_tcount) { - rp->r_refcount -= rp->r_tcount; - rp->r_tcount = 0; - } - break; - } - case DO_ALLOCATE: { - register i; - int j; - int tinstno; - int npos,npos2,pos[NREGS],pos2[NREGS]; - unsigned mincost,t; - struct reginfo *rp,**rpp; - token_t token,token2; - int propno; - int exactmatch; - int decision; - - if (codep[-1]&32) { - getint(propno,codep); - getint(tinstno,codep); - DEBUG("ALLOCATE,INIT"); - } else { - getint(propno,codep); - tinstno=0; - DEBUG("ALLOCATE,EMPTY"); - } - instance(tinstno,&token); - if (!forced) { - do { - npos=exactmatch=0; - for(rpp=reglist[propno];rp= *rpp; rpp++) - if (getrefcount((int)(rp-machregs), FALSE)==0) { - pos[npos++] = rp-machregs; - if (eqtoken(&rp->r_contents,&token)) - pos2[exactmatch++] = rp-machregs; + machregs[result.e_v.e_reg].r_contents.t_token = 0; + if (machregs[0].r_contents.t_token == -1 && machregs[0].r_contents.t_att[0].ar == result.e_v.e_reg) + { + machregs[0].r_contents.t_token = 0; + } } - /* + for (tp = &fakestack[stackheight - tokpatlen - 1]; tp >= &fakestack[0]; tp--) + if (tp->t_token == -1) + { + if (tp->t_att[0].ar == result.e_v.e_reg) + goto gotone; + } + else + { + tdp = &tokens[tp->t_token]; + for (i = 0; i < TOKENSIZE; i++) + if (tdp->t_type[i] == EV_REG && tp->t_att[i].ar == result.e_v.e_reg) + goto gotone; + } + break; + gotone: + /* investigate possible coercion to register */ + totalcost += stackupto(tp, ply, toplevel); + CHKCOST(); + break; + } + case DO_DEALLOCATE: + { + register i; + tkdef_p tdp; + int tinstno; + token_t token; + + DEBUG("DEALLOCATE"); + getint(tinstno, codep); + instance(tinstno, &token); + if (token.t_token == -1) + chrefcount(token.t_att[0].ar, -1, TRUE); + else + { + tdp = &tokens[token.t_token]; + for (i = 0; i < TOKENSIZE; i++) + if (tdp->t_type[i] == EV_REG) + chrefcount(token.t_att[i].ar, -1, TRUE); + } + break; + } + case DO_REALLOCATE: + { + struct reginfo* rp; + + DEBUG("REALLOCATE"); + for (rp = machregs + 1; rp < machregs + NREGS; rp++) + if (rp->r_tcount) + { + rp->r_refcount -= rp->r_tcount; + rp->r_tcount = 0; + } + break; + } + case DO_ALLOCATE: + { + register i; + int j; + int tinstno; + int npos, npos2, pos[NREGS], pos2[NREGS]; + unsigned mincost, t; + struct reginfo *rp, **rpp; + token_t token, token2; + int propno; + int exactmatch; + int decision; + + if (codep[-1] & 32) + { + getint(propno, codep); + getint(tinstno, codep); + DEBUG("ALLOCATE,INIT"); + } + else + { + getint(propno, codep); + tinstno = 0; + DEBUG("ALLOCATE,EMPTY"); + } + instance(tinstno, &token); + if (!forced) + { + do + { + npos = exactmatch = 0; + for (rpp = reglist[propno]; rp = *rpp; rpp++) + if (getrefcount((int)(rp - machregs), FALSE) == 0) + { + pos[npos++] = rp - machregs; + if (eqtoken(&rp->r_contents, &token)) + pos2[exactmatch++] = rp - machregs; + } + /* * Now pos[] contains all free registers with desired * property. If none then some stacking has to take place. */ - if (npos==0) { - if (stackheight<=tokpatlen) { - if (!toplevel) { - BROKE(); - } else { - if (paniced) - fatal("No regs available"); - totalcost += stackupto( &fakestack[0],ply,toplevel); - goto panic; - } - } - totalcost += stackupto( &fakestack[0],ply,toplevel); - CHKCOST(); - } - } while (npos==0); + if (npos == 0) + { + if (stackheight <= tokpatlen) + { + if (!toplevel) + { + BROKE(); + } + else + { + if (paniced) + fatal("No regs available"); + totalcost += stackupto(&fakestack[0], ply, toplevel); + goto panic; + } + } + totalcost += stackupto(&fakestack[0], ply, toplevel); + CHKCOST(); + } + } while (npos == 0); - if (!exactmatch && tinstno!=0) { - /* + if (!exactmatch && tinstno != 0) + { + /* * No exact match, but we were looking for a particular * token. Now try to find registers of which no * known contents is available (the others might still * be useful). */ - for (i=0;i costlimit) + BROKE(); + } + } + else + { + decision = forced; + if (getrefcount(decision, FALSE) != 0) + BROKE(); + token2.t_token = -1; + } + chrefcount(decision, 1, FALSE); + token2.t_att[0].ar = decision; if (token.t_token != 0) - t=move(&token,&token2,ply,FALSE,mincost); - else { - t = 0; - erasereg(pos2[j]); + { + totalcost += move(&token, &token2, ply, toplevel, MAXINT); + CHKCOST(); } - if (tcostlimit) - BROKE(); - } - } else { - decision = forced; - if (getrefcount(decision, FALSE)!=0) - BROKE(); - token2.t_token = -1; - } - chrefcount(decision,1,FALSE); - token2.t_att[0].ar=decision; - if (token.t_token != 0) { - totalcost+=move(&token,&token2,ply,toplevel,MAXINT); - CHKCOST(); - } else - erasereg(decision); - allreg[nallreg++]=decision; - break; - } - case DO_INSTR: { - register i; - int n; - int tinstno; - token_t token; - int stringno; + case DO_INSTR: + { + register i; + int n; + int tinstno; + token_t token; + int stringno; - DEBUG("INSTR"); - n=((codep[-1]>>5)&07); - getint(stringno,codep); - if (toplevel) { - swtxt(); - if (stringno>10000) { - assert(stringno < 100001 + MAXPROCARG); - genstr(procarg[stringno-10001]); - } else - genstr(stringno); - } - for(i=0;i0) - totalcost += tokens[token.t_token].t_cost.ct_space; - } - if (toplevel) - gennl(); - CHKCOST(); - break; - } - case DO_MOVE: { - int tinstno; - token_t token,token2; + DEBUG("INSTR"); + n = ((codep[-1] >> 5) & 07); + getint(stringno, codep); + if (toplevel) + { + swtxt(); + if (stringno > 10000) + { + assert(stringno < 10001 + MAXPROCARG); + genstr(procarg[stringno - 10001]); + } + else + genstr(stringno); + } + for (i = 0; i < n; i++) + { + getint(tinstno, codep); + instance(tinstno, &token); + if (toplevel) + prtoken(&token, i == 0 ? ' ' : ','); + if (token.t_token > 0) + totalcost += tokens[token.t_token].t_cost.ct_space; + } + if (toplevel) + gennl(); + CHKCOST(); + break; + } + case DO_MOVE: + { + int tinstno; + token_t token, token2; - DEBUG("MOVE"); - getint(tinstno,codep); - instance(tinstno,&token); - getint(tinstno,codep); - instance(tinstno,&token2); - totalcost += move(&token,&token2,ply,toplevel,costlimit-totalcost+1); - CHKCOST(); - break; - } - case DO_TEST: { - int tinstno; - token_t token; + DEBUG("MOVE"); + getint(tinstno, codep); + instance(tinstno, &token); + getint(tinstno, codep); + instance(tinstno, &token2); + totalcost += move(&token, &token2, ply, toplevel, costlimit - totalcost + 1); + CHKCOST(); + break; + } + case DO_TEST: + { + int tinstno; + token_t token; - DEBUG("TEST"); - getint(tinstno,codep); - instance(tinstno,&token); - totalcost += test(&token,ply,toplevel,costlimit-totalcost+1); - CHKCOST(); - break; - } - case DO_SETCC: { - int tinstno; - token_t token; + DEBUG("TEST"); + getint(tinstno, codep); + instance(tinstno, &token); + totalcost += test(&token, ply, toplevel, costlimit - totalcost + 1); + CHKCOST(); + break; + } + case DO_SETCC: + { + int tinstno; + token_t token; - DEBUG("SETCC"); - getint(tinstno,codep); - instance(tinstno,&token); - setcc(&token); - break; - } - case DO_ERASE: { - int nodeno; - result_t result; + DEBUG("SETCC"); + getint(tinstno, codep); + instance(tinstno, &token); + setcc(&token); + break; + } + case DO_ERASE: + { + int nodeno; + result_t result; - DEBUG("ERASE"); - getint(nodeno,codep); - compute(&enodes[nodeno], &result); - assert(result.e_typ!=EV_INT && result.e_typ!=EV_ADDR); - if (result.e_typ==EV_REG) - { - int regno = result.e_v.e_reg; - erasereg(regno); - } - break; - } - case DO_TOKREPLACE: { - register i; - int tinstno; - int repllen; - token_t reptoken[MAXREPLLEN]; + DEBUG("ERASE"); + getint(nodeno, codep); + compute(&enodes[nodeno], &result); + assert(result.e_typ != EV_INT && result.e_typ != EV_ADDR); + if (result.e_typ == EV_REG) + { + int regno = result.e_v.e_reg; + erasereg(regno); + } + break; + } + case DO_TOKREPLACE: + { + register i; + int tinstno; + int repllen; + token_t reptoken[MAXREPLLEN]; - DEBUG("TOKREPLACE"); - assert(stackheight>=tokpatlen); - repllen=(codep[-1]>>5)&07; + DEBUG("TOKREPLACE"); + assert(stackheight >= tokpatlen); + repllen = (codep[-1] >> 5) & 07; #ifndef NDEBUG - if (Debug>2) - fprintf(stderr,"Stackheight=%d, tokpatlen=%d, repllen=%d %s\n", - stackheight,tokpatlen,repllen,inscoerc ? "(inscoerc)":""); + if (Debug > 2) + fprintf(stderr, "Stackheight=%d, tokpatlen=%d, repllen=%d %s\n", + stackheight, tokpatlen, repllen, inscoerc ? "(inscoerc)" : ""); #endif - for(i=0;i>5)&07; - j=emp-emlines; - if (emrepllen>j) { - assert(nemlines+emrepllen-j=0;i--) - emlines[i+emrepllen-j] = emlines[i]; - nemlines += emrepllen-j; - emp += emrepllen-j; - } - emp -= emrepllen; - for (i=0;i> 5) & 07; + j = emp - emlines; + if (emrepllen > j) + { + assert(nemlines + emrepllen - j < MAXEMLINES); + for (i = nemlines; i >= 0; i--) + emlines[i + emrepllen - j] = emlines[i]; + nemlines += emrepllen - j; + emp += emrepllen - j; + } + emp -= emrepllen; + for (i = 0; i < emrepllen; i++) + { + getint(eminstr, codep); + getint(nodeno, codep); + emp[i].em_instr = eminstr; + compute(&enodes[nodeno], &result[i]); + } + for (i = 0; i < emrepllen; i++) + { + switch (result[i].e_typ) + { + default: + assert(FALSE); + case 0: + emp[i].em_optyp = OPNO; + emp[i].em_soper = 0; + break; + case EV_INT: + emp[i].em_optyp = OPINT; + emp[i].em_soper = tostring(result[i].e_v.e_con); + emp[i].em_u.em_ioper = result[i].e_v.e_con; + break; + case EV_ADDR: + emp[i].em_optyp = OPSYMBOL; + emp[i].em_soper = ad2str(result[i].e_v.e_addr); + break; + } + } + if (!toplevel) + { + ply += emrepllen; #ifndef NDEBUG - if (Debug > 4) - fprintf(stderr, "ply becomes %d\n", ply); + if (Debug > 4) + fprintf(stderr, "ply becomes %d\n", ply); #endif - } - break; - } - case DO_COST: { - cost_t cost; + } + break; + } + case DO_COST: + { + cost_t cost; - DEBUG("COST"); - getint(cost.ct_space,codep); - getint(cost.ct_time,codep); - totalcost += costcalc(cost); - CHKCOST(); - break; - } + DEBUG("COST"); + getint(cost.ct_space, codep); + getint(cost.ct_time, codep); + totalcost += costcalc(cost); + CHKCOST(); + break; + } #ifdef REGVARS - case DO_PRETURN: { - if (toplevel) { - swtxt(); - regreturn(); /* in mach.c */ - } - break; - } + case DO_PRETURN: + { + if (toplevel) + { + swtxt(); + regreturn(); /* in mach.c */ + } + break; + } #endif - case DO_RETURN: - DEBUG("RETURN"); - assert(origcp!=startupcode); + case DO_RETURN: + DEBUG("RETURN"); + assert(origcp != startupcode); #ifndef NDEBUG - level--; + level--; #endif - return(totalcost); + return (totalcost); #ifdef USE_TES - case DO_LABDEF: { - int index; + case DO_LABDEF: + { + int index; - DEBUG("LABDEF"); - getint(index,codep); - if (toplevel) { - swtxt(); - printlabel(index); - } + DEBUG("LABDEF"); + getint(index, codep); + if (toplevel) + { + swtxt(); + printlabel(index); + } - break; - } + break; + } #endif + } } - } - doreturn: +doreturn: #ifdef ALLOW_NEXTEM - if (toplevel && totalcost == INFINITY && ! paniced) { + if (toplevel && totalcost == INFINITY && !paniced) + { DEBUG("PANIC!"); - totalcost += stackupto(&fakestack[stackheight-1], ply, toplevel); + totalcost += stackupto(&fakestack[stackheight - 1], ply, toplevel); #ifndef NDEBUG if (Debug > 2) fprintf(stderr, "Stackheight = %d\n", stackheight); @@ -929,18 +1090,21 @@ normalfailed: if (stackpad!=tokpatlen) { #ifndef NDEBUG level--; #endif - return(totalcost); + return (totalcost); } -readcodebytes() { +readcodebytes() +{ #ifndef CODEINC register fd; extern int ncodebytes; - if ((fd=open("code",0))<0) { + if ((fd = open("code", 0)) < 0) + { error("Can't open code"); } - if (read(fd,coderules,ncodebytes)!=ncodebytes) { + if (read(fd, coderules, ncodebytes) != ncodebytes) + { error("Short read from code"); } close(fd); @@ -948,30 +1112,34 @@ readcodebytes() { } #ifdef TABLEDEBUG -initlset(f) char *f; { - extern char *myalloc(); +initlset(f) char* f; +{ + extern char* myalloc(); set_flag = f; - if ((set_fd=open(f+1,2))<0) - error("Can't open %s rw",f+1); - read(set_fd,&set_size,sizeof(int)); - set_val=( short *) myalloc(set_size); - read(set_fd,set_val,set_size); + if ((set_fd = open(f + 1, 2)) < 0) + error("Can't open %s rw", f + 1); + read(set_fd, &set_size, sizeof(int)); + set_val = (short*)myalloc(set_size); + read(set_fd, set_val, set_size); } -termlset() { +termlset() +{ - if (set_fd) { - lseek(set_fd,(long) sizeof(int),0); - write(set_fd,set_val,set_size); + if (set_fd) + { + lseek(set_fd, (long)sizeof(int), 0); + write(set_fd, set_val, set_size); close(set_fd); - if (set_flag[0]=='u') { + if (set_flag[0] == 'u') + { register i; - - fprintf(stderr,"Unused code rules:\n\n"); - for(i=0;i<8*set_size;i++) - if(set_val[i>>4]&(1<<(i&017))) - fprintf(stderr,"\"%s\", line %d\n",tablename,i); + + fprintf(stderr, "Unused code rules:\n\n"); + for (i = 0; i < 8 * set_size; i++) + if (set_val[i >> 4] & (1 << (i & 017))) + fprintf(stderr, "\"%s\", line %d\n", tablename, i); } } } diff --git a/mach/proto/ncg/salloc.c b/mach/proto/ncg/salloc.c index e110d75ad..7ce1287bb 100644 --- a/mach/proto/ncg/salloc.c +++ b/mach/proto/ncg/salloc.c @@ -37,7 +37,7 @@ void chkstr(); string myalloc(size) { register string p; - p = (string) malloc((unsigned)size); + p = (string) calloc((unsigned)size, 1); if (p==0) fatal("Out of memory"); return(p); diff --git a/mach/z80/int/em22 b/mach/z80/int/em22 index 8591c7bfc..d30597a0e 100644 --- a/mach/z80/int/em22 +++ b/mach/z80/int/em22 @@ -25,17 +25,17 @@ name asld mapflag -s* SIZE_FLAG=-s* mapflag -ansi C_LIB={EM}/{LIB}ac args {SIZE_FLAG} \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.mod={EM}/{RT}m2) \ ({RTS}:.p={EM}/{RT}pc) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ (.b.c.ocm.mod.p.e:{TAIL}={EM}/{LIB}mon) \ ({RTS}{ANSI?}:.cansi={EM}/lib/em22/end_em) diff --git a/man/powerpc_as.6 b/man/powerpc_as.6 new file mode 100644 index 000000000..8198d6bce --- /dev/null +++ b/man/powerpc_as.6 @@ -0,0 +1,33 @@ +.TH POWERPC_AS 1 +.ad +.SH NAME +powerpc_as \- assembler for PowerPC + +.SH SYNOPSIS +as [options] argument ... + +.SH DESCRIPTION +This assembler is made with the general framework +described in \fIuni_ass\fP(6). + +.SH SYNTAX +Most 32-bit integer and floating point instructions are supported, but not many +short form instructions. Instructions which take 16-bit operands can additionally +use the following special functions: + +.IP hi16[value], ha16[value] +Returns the high half of the value of the expression; if the value is not absolute, +also generates the appropriate fixup. Use of either of these \fImust\fR be followed, +in the next instruction, by the corresponding use of \fBlo16[]\fR. Use \fBhi16[]\fR +if the low half is going to interpret its payload as an unsigned value, and +\fBha16[]\fR if it will be interpreted as a signed value (so that the high half can +be adjusted to match). + +.IP lo16[] +Returns the low half of the value of the expression. No fixup is generated. Use of +\fBlo16[]\fR must come in the instruction immediately after a use of \fBhi16[]\fR or +\fBha16[]\fR. + +.SH "SEE ALSO" +uni_ass(6), +ack(1) diff --git a/modules/src/object/build.lua b/modules/src/object/build.lua index c30c7e54a..6a8bea04e 100644 --- a/modules/src/object/build.lua +++ b/modules/src/object/build.lua @@ -1,6 +1,7 @@ clibrary { name = "lib", srcs = { "./*.c" }, + hdrs = { "./object.h" }, deps = { "modules+headers", "h+local", diff --git a/modules/src/object/obj.h b/modules/src/object/obj.h index 8f7fd8d32..9000b32ce 100644 --- a/modules/src/object/obj.h +++ b/modules/src/object/obj.h @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/modules/src/object/object.h b/modules/src/object/object.h index 68a5ea99f..d6c218a2a 100644 --- a/modules/src/object/object.h +++ b/modules/src/object/object.h @@ -4,42 +4,46 @@ * See the copyright notice in the ACK home directory, in the file "Copyright". */ -#include - #ifndef __OBJECT_INCLUDED__ #define __OBJECT_INCLUDED__ -_PROTOTYPE(int wr_open, (char *f)); -_PROTOTYPE(void wr_close, (void)); -_PROTOTYPE(void wr_ohead, (struct outhead *h)); -_PROTOTYPE(void wr_sect, (struct outsect *s, unsigned int c)); -_PROTOTYPE(void wr_outsect, (int sectno)); -_PROTOTYPE(void wr_emit, (char *b, long c)); -_PROTOTYPE(void wr_putc, (int c)); -_PROTOTYPE(void wr_relo, (struct outrelo *r, unsigned int c)); -_PROTOTYPE(void wr_name, (struct outname *n, unsigned int c)); -_PROTOTYPE(void wr_string, (char *s, long c)); -_PROTOTYPE(void wr_arhdr, (int fd, struct ar_hdr *a)); -_PROTOTYPE(void wr_ranlib, (int fd, struct ranlib *r, long cnt)); -_PROTOTYPE(void wr_int2, (int fd, int i)); -_PROTOTYPE(void wr_long, (int fd, long l)); -_PROTOTYPE(void wr_bytes, (int fd, char *buf, long l)); -_PROTOTYPE(int rd_open, (char *f)); -_PROTOTYPE(int rd_fdopen, (int f)); -_PROTOTYPE(void rd_close, (void)); -_PROTOTYPE(void rd_ohead, (struct outhead *h)); -_PROTOTYPE(void rd_sect, (struct outsect *s, unsigned int c)); -_PROTOTYPE(void rd_outsect, (int sectno)); -_PROTOTYPE(void rd_emit, (char *b, long c)); -_PROTOTYPE(void rd_relo, (struct outrelo *r, unsigned int c)); -_PROTOTYPE(void rd_rew_relo, (struct outhead *head)); -_PROTOTYPE(void rd_name, (struct outname *n, unsigned int c)); -_PROTOTYPE(void rd_string, (char *s, long c)); -_PROTOTYPE(int rd_arhdr, (int fd, struct ar_hdr *a)); -_PROTOTYPE(void rd_ranlib, (int fd, struct ranlib *r, long cnt)); -_PROTOTYPE(int rd_int2, (int fd)); -_PROTOTYPE(long rd_long, (int fd)); -_PROTOTYPE(void rd_bytes, (int fd, char *buf, long l)); -_PROTOTYPE(int rd_fd, (void)); +struct ar_hdr; +struct outhead; +struct outrelo; +struct outsect; +struct ranlib; + +int wr_open(char *f); +void wr_close(void); +void wr_ohead(struct outhead *h); +void wr_sect(struct outsect *s, unsigned int c); +void wr_outsect(int sectno); +void wr_emit(char *b, long c); +void wr_putc(int c); +void wr_relo(struct outrelo *r, unsigned int c); +void wr_name(struct outname *n, unsigned int c); +void wr_string(char *s, long c); +void wr_arhdr(int fd, struct ar_hdr *a); +void wr_ranlib(int fd, struct ranlib *r, long cnt); +void wr_int2(int fd, int i); +void wr_long(int fd, long l); +void wr_bytes(int fd, char *buf, long l); +int rd_open(char *f); +int rd_fdopen(int f); +void rd_close(void); +void rd_ohead(struct outhead *h); +void rd_sect(struct outsect *s, unsigned int c); +void rd_outsect(int sectno); +void rd_emit(char *b, long c); +void rd_relo(struct outrelo *r, unsigned int c); +void rd_rew_relo(struct outhead *head); +void rd_name(struct outname *n, unsigned int c); +void rd_string(char *s, long c); +int rd_arhdr(int fd, struct ar_hdr *a); +void rd_ranlib(int fd, struct ranlib *r, long cnt); +int rd_int2(int fd); +long rd_long(int fd); +void rd_bytes(int fd, char *buf, long l); +int rd_fd(void); #endif /* __OBJECT_INCLUDED__ */ diff --git a/plat/build.lua b/plat/build.lua index 85ba61bc9..dc0821f26 100644 --- a/plat/build.lua +++ b/plat/build.lua @@ -15,6 +15,8 @@ definerule("ackfile", name = e.name, srcs = e.srcs, deps = { + "lang/b/compiler+pkg", + "lang/basic/src+pkg", "lang/cem/cemcom.ansi+pkg", "lang/cem/cpp.ansi+pkg", "lang/m2/comp+pkg", @@ -100,10 +102,12 @@ definerule("build_plat_libs", return installable { name = e.name, map = { + "lang/b/lib+pkg_"..e.plat, "lang/basic/lib+pkg_"..e.plat, "lang/cem/libcc.ansi+pkg_"..e.plat, "lang/m2/libm2+pkg_"..e.plat, "lang/pc/libpc+pkg_"..e.plat, + "lang/b/lib+pkg_"..e.plat, ["$(PLATIND)/"..e.plat.."/libem.a"] = "mach/"..e.arch.."/libem+lib_"..e.plat, ["$(PLATIND)/"..e.plat.."/libend.a"] = "mach/"..e.arch.."/libend+lib_"..e.plat, } diff --git a/plat/cpm/descr b/plat/cpm/descr index 2d626295a..d084f89ea 100644 --- a/plat/cpm/descr +++ b/plat/cpm/descr @@ -60,17 +60,19 @@ name led mapflag -i SEPID=-b1:0 mapflag -fp FLOATS={EM}/{ILIB}fp args {ALIGN} {SEPID?} \ + ({RTS}:.b=-u _i_main) \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ - ({RTS}:.ocm.b={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.ocm.bas.b={PLATFORMDIR}/c-ansi.o) \ ({RTS}:.c={PLATFORMDIR}/c-ansi.o) \ ({RTS}:.mod={PLATFORMDIR}/modula2.o) \ ({RTS}:.p={PLATFORMDIR}/pascal.o) \ -o > < \ (.p:{TAIL}={PLATFORMDIR}/libpascal.a) \ - (.b:{TAIL}={PLATFORMDIR}/libbasic.a) \ + (.b:{TAIL}={PLATFORMDIR}/libb.a) \ + (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ - (.ocm.b.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + (.ocm.bas.mod.b.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ diff --git a/plat/linux/libsys/execve.c b/plat/linux/libsys/execve.c new file mode 100644 index 000000000..d8f37b1cf --- /dev/null +++ b/plat/linux/libsys/execve.c @@ -0,0 +1,7 @@ +#include +#include "libsys.h" + +int execve(const char *path, char *const argv[], char *const envp[]) +{ + return _syscall(__NR_execve, (quad) path, (quad) argv, (quad) envp); +} diff --git a/plat/linux/libsys/sbrk.c b/plat/linux/libsys/sbrk.c index 7aeeecb86..f790a17cb 100644 --- a/plat/linux/libsys/sbrk.c +++ b/plat/linux/libsys/sbrk.c @@ -26,7 +26,6 @@ void* sbrk(int increment) { char* old; char* new; - char* actual; if (!current) current = (char*) _syscall(__NR_brk, 0, 0, 0); @@ -35,15 +34,21 @@ void* sbrk(int increment) return current; old = current; + new = old + increment; - actual = (char*) _syscall(__NR_brk, (quad) new, 0, 0); - if (actual < new) - { - errno = ENOMEM; - return OUT_OF_MEMORY; - } + if ((increment > 0) && (new <= old)) + goto out_of_memory; + else if ((increment < 0) && (new >= old)) + goto out_of_memory; + + if (brk(new) < 0) + goto out_of_memory; - current = actual; return old; + +out_of_memory: + errno = ENOMEM; + return OUT_OF_MEMORY; } + diff --git a/plat/linux/libsys/sigprocmask.c b/plat/linux/libsys/sigprocmask.c new file mode 100644 index 000000000..ad1b339c2 --- /dev/null +++ b/plat/linux/libsys/sigprocmask.c @@ -0,0 +1,7 @@ +#include +#include "libsys.h" + +int sigprocmask(int flags, const sigset_t *new, sigset_t *old) +{ + return _syscall(__NR_sigprocmask, flags, (quad) new, (quad) old); +} diff --git a/plat/linux386/build-tools.lua b/plat/linux386/build-tools.lua index d711f85fd..31b8a7388 100644 --- a/plat/linux386/build-tools.lua +++ b/plat/linux386/build-tools.lua @@ -16,6 +16,7 @@ return installable { ["$(PLATDEP)/linux386/as"] = "+as", ["$(PLATDEP)/linux386/ncg"] = "+ncg", ["$(PLATIND)/descr/linux386"] = "./descr", + "util/amisc+aelflod-pkg", "util/opt+pkg", } } diff --git a/plat/linux386/descr b/plat/linux386/descr index 611e96e44..1888e4182 100644 --- a/plat/linux386/descr +++ b/plat/linux386/descr @@ -56,17 +56,19 @@ name led mapflag -l* LNAME={PLATFORMDIR}/lib* mapflag -fp FLOATS={EM}/{LIB}fp args {ALIGN} {SEPID?} \ + ({RTS}:.b=-u _i_main) \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ - ({RTS}:.ocm.b={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.ocm.bas.b={PLATFORMDIR}/c-ansi.o) \ ({RTS}:.c={PLATFORMDIR}/c-ansi.o) \ ({RTS}:.mod={PLATFORMDIR}/modula2.o) \ ({RTS}:.p={PLATFORMDIR}/pascal.o) \ -o > < \ (.p:{TAIL}={PLATFORMDIR}/libpascal.a) \ - (.b:{TAIL}={PLATFORMDIR}/libbasic.a) \ + (.b:{TAIL}={PLATFORMDIR}/libb.a) \ + (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ - (.ocm.b.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + (.ocm.bas.mod.b.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ diff --git a/plat/linux386/include/unistd.h b/plat/linux386/include/unistd.h index 35dc8dde7..8c8637c09 100644 --- a/plat/linux386/include/unistd.h +++ b/plat/linux386/include/unistd.h @@ -56,7 +56,6 @@ extern int write(int fd, void* buffer, size_t count); extern off_t lseek(int fildes, off_t offset, int whence); extern int fcntl(int fd, int op, ...); extern int unlink(const char* path); -extern int remove(const char* path); /* Special variables */ @@ -69,6 +68,7 @@ extern pid_t getpid(void); extern int brk(void* ptr); extern void* sbrk(int increment); extern int isatty(int d); +extern int execve(const char *path, char *const argv[], char *const envp[]); /* Signal handling */ @@ -116,8 +116,16 @@ typedef int sig_atomic_t; #define _NSIG 32 /* Biggest signal number + 1 (not including real-time signals). */ + +/* sigprocmask */ +#define SIG_BLOCK 0 +#define SIG_UNBLOCK 1 +#define SIG_SETMASK 2 +typedef unsigned long sigset_t; + typedef void (*sighandler_t)(int); extern sighandler_t signal(int signum, sighandler_t handler); +extern int sigprocmask(int, const sigset_t *, sigset_t *); extern int raise(int signum); diff --git a/plat/linux386/tests/build.lua b/plat/linux386/tests/build.lua new file mode 100644 index 000000000..afd12fdce --- /dev/null +++ b/plat/linux386/tests/build.lua @@ -0,0 +1,7 @@ +include("tests/plat/build.lua") + +plat_testsuite { + name = "tests", + plat = "linux386", + method = "qemu-i386" +} diff --git a/plat/linux68k/build-tools.lua b/plat/linux68k/build-tools.lua index 944e57f47..03d659a15 100644 --- a/plat/linux68k/build-tools.lua +++ b/plat/linux68k/build-tools.lua @@ -16,6 +16,7 @@ return installable { ["$(PLATDEP)/linux68k/as"] = "+as", ["$(PLATDEP)/linux68k/ncg"] = "+ncg", ["$(PLATIND)/descr/linux68k"] = "./descr", + "util/amisc+aelflod-pkg", "util/opt+pkg", } } diff --git a/plat/linux68k/descr b/plat/linux68k/descr index 9347ad2b2..1e3b6a5bd 100644 --- a/plat/linux68k/descr +++ b/plat/linux68k/descr @@ -56,17 +56,19 @@ name led mapflag -l* LNAME={PLATFORMDIR}/lib* mapflag -fp FLOATS={EM}/{LIB}fp args {ALIGN} {SEPID?} \ + ({RTS}:.b=-u _i_main) \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ - ({RTS}:.ocm.b={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.ocm.bas.b={PLATFORMDIR}/c-ansi.o) \ ({RTS}:.c={PLATFORMDIR}/c-ansi.o) \ ({RTS}:.mod={PLATFORMDIR}/modula2.o) \ ({RTS}:.p={PLATFORMDIR}/pascal.o) \ -o > < \ (.p:{TAIL}={PLATFORMDIR}/libpascal.a) \ - (.b:{TAIL}={PLATFORMDIR}/libbasic.a) \ + (.b:{TAIL}={PLATFORMDIR}/libb.a) \ + (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ - (.ocm.b.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + (.ocm.bas.mod.b.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ diff --git a/plat/linux68k/include/unistd.h b/plat/linux68k/include/unistd.h index 307192f77..927a20459 100644 --- a/plat/linux68k/include/unistd.h +++ b/plat/linux68k/include/unistd.h @@ -55,6 +55,7 @@ extern int read(int fd, void* buffer, size_t count); extern int write(int fd, void* buffer, size_t count); extern off_t lseek(int fildes, off_t offset, int whence); extern int fcntl(int fd, int op, ...); +extern int unlink(const char* path); /* Special variables */ @@ -67,6 +68,7 @@ extern pid_t getpid(void); extern int brk(void* ptr); extern void* sbrk(int increment); extern int isatty(int d); +extern int execve(const char *path, char *const argv[], char *const envp[]); /* Signal handling */ @@ -114,8 +116,16 @@ typedef int sig_atomic_t; #define _NSIG 32 /* Biggest signal number + 1 (not including real-time signals). */ + +/* sigprocmask */ +#define SIG_BLOCK 0 +#define SIG_UNBLOCK 1 +#define SIG_SETMASK 2 +typedef unsigned long sigset_t; + typedef void (*sighandler_t)(int); extern sighandler_t signal(int signum, sighandler_t handler); +extern int sigprocmask(int, const sigset_t *, sigset_t *); extern int raise(int signum); diff --git a/plat/linuxppc/build-tools.lua b/plat/linuxppc/build-tools.lua index ce1a163d8..e48524cc9 100644 --- a/plat/linuxppc/build-tools.lua +++ b/plat/linuxppc/build-tools.lua @@ -28,6 +28,7 @@ return installable { ["$(PLATDEP)/linuxppc/mcg"] = "+mcg", ["$(PLATDEP)/linuxppc/top"] = "+top", ["$(PLATIND)/descr/linuxppc"] = "./descr", + "util/amisc+aelflod-pkg", "util/opt+pkg", } } diff --git a/plat/linuxppc/descr b/plat/linuxppc/descr index 12bece6e9..ced1de4b1 100644 --- a/plat/linuxppc/descr +++ b/plat/linuxppc/descr @@ -62,17 +62,19 @@ name led mapflag -l* LNAME={PLATFORMDIR}/lib* mapflag -fp FLOATS={EM}/{LIB}fp args {ALIGN} {SEPID?} \ + ({RTS}:.b=-u _i_main) \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ - ({RTS}:.ocm.b={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.ocm.bas.b={PLATFORMDIR}/c-ansi.o) \ ({RTS}:.c={PLATFORMDIR}/c-ansi.o) \ ({RTS}:.mod={PLATFORMDIR}/modula2.o) \ ({RTS}:.p={PLATFORMDIR}/pascal.o) \ -o > < \ (.p:{TAIL}={PLATFORMDIR}/libpascal.a) \ - (.b:{TAIL}={PLATFORMDIR}/libbasic.a) \ + (.b:{TAIL}={PLATFORMDIR}/libb.a) \ + (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ - (.ocm.b.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + (.ocm.bas.mod.b.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ diff --git a/plat/linuxppc/include/unistd.h b/plat/linuxppc/include/unistd.h index 307192f77..f57705365 100644 --- a/plat/linuxppc/include/unistd.h +++ b/plat/linuxppc/include/unistd.h @@ -55,6 +55,7 @@ extern int read(int fd, void* buffer, size_t count); extern int write(int fd, void* buffer, size_t count); extern off_t lseek(int fildes, off_t offset, int whence); extern int fcntl(int fd, int op, ...); +extern int unlink(const char* path); /* Special variables */ @@ -67,6 +68,7 @@ extern pid_t getpid(void); extern int brk(void* ptr); extern void* sbrk(int increment); extern int isatty(int d); +extern int execve(const char *path, char *const argv[], char *const envp[]); /* Signal handling */ @@ -114,8 +116,34 @@ typedef int sig_atomic_t; #define _NSIG 32 /* Biggest signal number + 1 (not including real-time signals). */ + +/* sigprocmask */ +#define SIG_BLOCK 0 +#define SIG_UNBLOCK 1 +#define SIG_SETMASK 2 +typedef unsigned long sigset_t; + +/* sa_flags */ +#define SA_NODEFER 0x40000000UL +#define SA_RESETHAND 0x80000000UL + +struct __siginfo; +struct sigaction { + union { + void (*__sa_handler)(int); + void (*__sa_sigaction)(int, struct __siginfo *, void *); + } __sigaction_u; + sigset_t sa_mask; + unsigned long sa_flags; + void (*sa_restorer)(void); +}; +#define sa_handler __sigaction_u.__sa_handler +#define sa_sigaction __sigaction_u.__sa_sigaction + typedef void (*sighandler_t)(int); +extern int sigaction(int, const struct sigaction *, struct sigaction *); extern sighandler_t signal(int signum, sighandler_t handler); +extern int sigprocmask(int, const sigset_t *, sigset_t *); extern int raise(int signum); diff --git a/plat/linuxppc/libsys/build.lua b/plat/linuxppc/libsys/build.lua index e74f3f416..f7b16b378 100644 --- a/plat/linuxppc/libsys/build.lua +++ b/plat/linuxppc/libsys/build.lua @@ -1,16 +1,36 @@ acklibrary { - name = "lib", - srcs = { - "./*.s", - "plat/linux/libsys/*.c", - "plat/linux/libsys/*.s", - }, + name = "lib", + srcs = { + "./_syscall.s", + "./sigaction.s", + "./signal.c", + "./trap.s", + "plat/linux/libsys/_exit.c", + "plat/linux/libsys/_hol0.s", + "plat/linux/libsys/close.c", + "plat/linux/libsys/creat.c", + "plat/linux/libsys/errno.s", + "plat/linux/libsys/execve.c", + "plat/linux/libsys/getpid.c", + "plat/linux/libsys/gettimeofday.c", + "plat/linux/libsys/ioctl.c", + "plat/linux/libsys/isatty.c", + "plat/linux/libsys/kill.c", + "plat/linux/libsys/lseek.c", + "plat/linux/libsys/open.c", + "plat/linux/libsys/read.c", + "plat/linux/libsys/sbrk.c", + -- omit signal.c + "plat/linux/libsys/sigprocmask.c", + "plat/linux/libsys/unlink.c", + "plat/linux/libsys/write.c", + }, deps = { "lang/cem/libcc.ansi/headers+headers", "plat/linuxppc/include+headers", }, - vars = { - plat = "linuxppc" - } + vars = { + plat = "linuxppc" + } } diff --git a/plat/linuxppc/libsys/sigaction.s b/plat/linuxppc/libsys/sigaction.s new file mode 100644 index 000000000..0509c8e72 --- /dev/null +++ b/plat/linuxppc/libsys/sigaction.s @@ -0,0 +1,156 @@ +#define __NR_sigaction 67 +#define SIG_BLOCK 0 +#define SIG_SETMASK 2 +#define MAXSIG 32 + +/* offsets into our stack frame */ +#define mynew 16 /* new sigaction */ +#define mynset 32 /* new signal set */ +#define myoset 36 /* old signal set */ +#define mysave 40 +#define mysize 56 + +.sect .text; .sect .rodata; .sect .data; .sect .bss + +/* + * Linux calls signal handlers with arguments in registers, but the + * ACK expects arguments on the stack. This sigaction() uses a + * "bridge" to move the arguments. + */ +.sect .text +.define _sigaction +_sigaction: + mflr r0 + subi r1, r1, mysize + stw r31, mysave+8(r1) + stw r30, mysave+4(r1) + stw r29, mysave(r1) + stw r0, mysave+12(r1) + li r3, 0 + stw r3, mynset(r1) ! mynset = 0 + lwz r29, mysize(r1) ! r29 = signal number + lwz r30, mysize+4(r1) ! r30 = new action + lwz r31, mysize+8(r1) ! r31 = old action + /* + * If the new action is non-NULL, the signal number is in + * range 1 to MAXSIG, and the new handler is not SIG_DFL 0 + * or SIG_IGN 1, then we interpose our bridge. + */ + cmpwi cr0, r30, 0 + subi r7, r29, 1 ! r7 = index in handlers + cmplwi cr7, r7, MAXSIG ! unsigned comparison + beq cr0, kernel + bge cr7, kernel + lwz r3, 0(r30) ! r3 = new handler + clrrwi. r3, r3, 1 + beq cr0, kernel + /* + * Block the signal while we build the bridge. Prevents a + * race if a signal arrives after we change the bridge but + * before we change the action in the kernel. + */ + li r4, 1 + slw r4, r4, r7 + stw r4, mynset(r1) ! mynmask = 1 << (signal - 1) + li r3, SIG_BLOCK + la r4, mynset(r1) + la r5, myoset(r1) + stw r3, 0(r1) + stw r4, 4(r1) + stw r5, 8(r1) + bl _sigprocmask + /* + * Point our bridge to the new signal handler. Then copy the + * new sigaction but point it to our bridge. + */ + lis r6, hi16[handlers] + ori r6, r6, lo16[handlers] + subi r7, r29, 1 + slwi r7, r7, 2 + lwz r3, 0(r30) ! r3 = new handler + stwx r3, r6, r7 ! put it in array of handlers + lis r3, hi16[bridge] + ori r3, r3, lo16[bridge] + lwz r4, 4(r30) + lwz r5, 8(r30) + lwz r6, 12(r30) + stw r3, mynew(r1) ! sa_handler or sa_sigaction + stw r4, mynew+4(r1) ! sa_mask + stw r5, mynew+8(r1) ! sa_flags + stw r6, mynew+12(r1) ! sa_restorer + la r30, mynew(r1) +kernel: + li r3, __NR_sigaction + stw r3, 0(r1) + stw r29, 4(r1) + stw r30, 8(r1) + stw r31, 12(r1) + bl __syscall + /* + * If we blocked the signal, then restore the old signal mask. + */ + lwz r3, mynset(r1) + cmpwi cr0, r3, 0 + beq cr0, fixold + li r3, SIG_SETMASK + la r4, myoset(r1) + li r5, 0 + stw r3, 0(r1) + stw r4, 4(r1) + stw r5, 8(r1) + bl _sigprocmask + /* + * If the old sigaction is non-NULL and points to our bridge, + * then point it to the signal handler. + */ +fixold: + cmpwi cr0, r31, 0 + beq cr0, leave + lis r3, hi16[bridge] + ori r3, r3, lo16[bridge] + lwz r4, 0(r31) + cmpw cr0, r3, r4 + bne cr0, leave + lis r6, hi16[handlers] + ori r6, r6, lo16[handlers] + subi r7, r29, 1 + slwi r7, r7, 2 + lwzx r3, r6, r7 ! get it from array of handlers + stw r3, 0(r31) ! put it in old sigaction +leave: + lwz r0, mysave+12(r1) + lwz r29, mysave(r1) + lwz r30, mysave+4(r1) + lwz r31, mysave+8(r1) + addi r1, r1, mysize + mtlr r0 + blr ! return from sigaction + +/* + * Linux calls bridge(signum) or bridge(signum, info, context) with + * arguments in registers r3, r4, r5. + */ +bridge: + mflr r0 + subi r1, r1, 16 + stw r0, 12(r1) + stw r3, 0(r1) ! signal number + stw r4, 4(r1) ! info + stw r5, 8(r1) ! context + + lis r6, hi16[handlers] + ori r6, r6, lo16[handlers] + subi r7, r3, 1 + slwi r7, r7, 2 + lwzx r6, r6, r7 + mtctr r6 + bctrl ! call our signal handler + + lwz r0, 12(r1) + addi r1, r1, 16 + mtlr r0 + blr ! return from bridge + +.sect .bss +handlers: + .space 4 * MAXSIG ! array of signal handlers diff --git a/plat/linuxppc/libsys/signal.c b/plat/linuxppc/libsys/signal.c new file mode 100644 index 000000000..0ed1918e1 --- /dev/null +++ b/plat/linuxppc/libsys/signal.c @@ -0,0 +1,19 @@ +#include + +/* + * Uses our bridge in sigaction.s when calling the signal handler. + * Mimics Linux __NR_signal by using SA_NODEFER | SA_RESETHAND. + */ +sighandler_t signal(int signum, sighandler_t handler) { + struct sigaction new, old; + int i; + + new.sa_handler = handler; + new.sa_mask = 0; /* empty set */ + new.sa_flags = SA_NODEFER | SA_RESETHAND; + + i = sigaction(signum, &new, &old); + if (i < 0) + return SIG_ERR; + return old.sa_handler; +} diff --git a/plat/linuxppc/libsys/trap.s b/plat/linuxppc/libsys/trap.s index 09d3b0b21..93c5189a4 100644 --- a/plat/linuxppc/libsys/trap.s +++ b/plat/linuxppc/libsys/trap.s @@ -52,43 +52,50 @@ EUNIMPL = 63 ! unimplemented em-instruction called .trap_ecase: addi r3, r0, ECASE b .trap - + .define .trap_earray .trap_earray: addi r3, r0, EARRAY b .trap - + +.define .trap_erange +.trap_erange: + addi r3, r0, ERANGE + b .trap + +.define .trp .define .trap +.trp: .trap: cmpi cr0, 0, r3, 15 ! traps >15 can't be ignored bc IFTRUE, LT, 1f - + addi r4, r0, 1 rlwnm r4, r4, r3, 0, 31 ! calculate trap bit li32 r5, .ignmask lwz r5, 0(r5) ! load ignore mask and. r4, r4, r5 ! compare bclr IFFALSE, EQ, 0 ! return if non-zero - + 1: li32 r4, .trppc lwz r5, 0(r4) ! load user trap routine or. r5, r5, r5 ! test bc IFTRUE, EQ, fatal ! if no user trap routine, bail out - + addi r0, r0, 0 stw r0, 0(r4) ! reset trap routine - + mfspr r0, lr stwu r0, -4(sp) ! save old lr - + stwu r3, -4(sp) mtspr ctr, r5 bcctrl ALWAYS, 0, 0 ! call trap routine - + lwz r0, 4(sp) ! load old lr again addi sp, sp, 8 ! retract over stack usage - bclr ALWAYS, 0, 0 ! return + bclr ALWAYS, 0, 0 ! return fatal: addi r3, r0, 1 @@ -96,7 +103,7 @@ fatal: addi r5, r0, 6 addi r0, r0, 4 ! write() sc 0 - + addi r0, r0, 1 ! exit() sc 0 diff --git a/plat/linuxppc/tests/build.lua b/plat/linuxppc/tests/build.lua new file mode 100644 index 000000000..7601ab0be --- /dev/null +++ b/plat/linuxppc/tests/build.lua @@ -0,0 +1,7 @@ +include("tests/plat/build.lua") + +plat_testsuite { + name = "tests", + plat = "linuxppc", + method = "qemu-ppc" +} diff --git a/plat/osx/cvmach/build.lua b/plat/osx/cvmach/build.lua new file mode 100644 index 000000000..8076546c1 --- /dev/null +++ b/plat/osx/cvmach/build.lua @@ -0,0 +1,15 @@ +cprogram { + name = "cvmach", + srcs = { "./cvmach.c" }, + deps = { + "h+emheaders", + "modules/src/object+lib", + } +} + +installable { + name = "pkg", + map = { + ["$(PLATDEP)/cvmach"] = "+cvmach", + } +} diff --git a/plat/osx/cvmach/cvmach.6 b/plat/osx/cvmach/cvmach.6 new file mode 100644 index 000000000..30d4aa2d7 --- /dev/null +++ b/plat/osx/cvmach/cvmach.6 @@ -0,0 +1,96 @@ +.Dd December 2, 2016 +.Dt CVMACH 6 +.Os +.Sh NAME +.Nm cvmach +.Nd convert an executable file from ack.out to Mach-o +.Sh SYNOPSIS +.Cm ~em/lib/ack/cvmach +.Fl m Ns Ar number +.Oo +.Ar infile +.Op Ar outfile +.Oc +.Sh DESCRIPTION +The +.Nm +utility converts an executable file from +.Xr ack.out 5 +format to Mach-object format. +It can produce Mach-o executables for Mac OS X. +If the +.Ar infile +or +.Ar outfile +are not given, then +.Nm +reads from standard input or writes to standard output. +.Pp +The option is required: +.Bl -tag -width Ds +.It Fl m Ns Ar number +Sets the CPU type in the Mach header. +This must be +.Fl m Ns Cm 7 +for Intel i386 or +.Fl m Ns Cm 18 +for PowerPC. +.Nm +doesn't know how to make Mach-o files for other CPU types. +.El +.Pp +The input file must have four segments: +TEXT, ROM, DATA and BSS, in that order. +.Nm +converts them into four Mach sections in two Mach segments. +TEXT and ROM go in the RX segment (Read and eXecute). +DATA and BSS go in the RW segment (Read and Write). +.Nm +sets the page protection so programs can't write the RX segment, +and can't execute the RW segment. +The program will begin execution at the beginning of TEXT. +.Pp +.Nm +also converts the symbol table. +.Sh DIAGNOSTICS +.Bl -diag +.It text segment must have base 0x%lx, not 0x%lx +TEXT must begin immediately after the Mach header and load commands. +The message gives the correct +.Ar base . +Relinking the program with +.Cm em_led Fl b Ns 0: Ns Ar base +would fix it. +.It the %s segment must follow the %s segment. +TEXT and ROM must be continuous in memory, because +.Nm +maps them in the same Mach segment. +Likewise, DATA and BSS must be contiguous. +There may be a small gap between TEXT and ROM, or between DATA and +BSS, only if the gap is necessary to align ROM or BSS. +.It the data and rom segments are too close. +DATA and ROM must not share a page in memory, because +.Nm +maps them in different Mach segments, with different page protections. +The page size for i386 and PowerPC is 4096 or 0x1000 bytes. +For example, if ROM ends at address 0x2bed, +then DATA may not begin at 0x2bf0, because +.Nm +can't put the page from 0x2000 to 0x2fff in both Mach segments. +Relinking the program with +.Cm em_led Fl a Ns 2:4096 +would fix it. +.It the bss space contains initialized data. +BSS must not contain initialized data, because +.Nm +converts it to a zero-fill section. +.El +.Sh CAVEATS +Mac OS X 10.4 for PowerPC does not protect pages against execution. +All mapped pages are executable, whether or not the execute bit is set +in the page protection. +.Nm +can't prevent the execution of the RW segment. +.Sh BUGS +The symbol conversion preserves the name and value of each symbol, but +may lose other information, such as the symbol type. diff --git a/plat/osx/cvmach/cvmach.c b/plat/osx/cvmach/cvmach.c new file mode 100644 index 000000000..5f8315ddd --- /dev/null +++ b/plat/osx/cvmach/cvmach.c @@ -0,0 +1,665 @@ +/* + * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. + * See the copyright notice in the ACK home directory, in the file "Copyright". + */ + +/* + * cvmach.c - convert ack.out to Mach-o + * + * Mostly pinched from aelflod (util/amisc/aelflod.c), which pinched + * from the ARM cv (mach/arm/cv/cv.c), which pinched from the m68k2 cv + * (mach/m68k2/cv/cv.c). The code to read ack.out format using + * libobject is pinched from the Xenix i386 cv (mach/i386/cv/cv.c). + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +/* Header and section table of ack.out */ +struct outhead outhead; +struct outsect outsect[S_MAX]; +uint32_t ack_off_char; /* Offset of string table in ack.out */ + +int bigendian; /* Emit big-endian Mach-o? */ +int cpu_type; +uint32_t entry; /* Virtual address of entry point */ +uint32_t sz_thread_command; + +char *outputfile = NULL; /* Name of output file, or NULL */ +char *program; /* Name of current program: argv[0] */ +FILE *output; /* Output stream */ +#define writef(a, b, c) fwrite((a), (b), (c), output) + +/* Segment numbers in ack.out */ +enum { + TEXT = 0, + ROM, + DATA, + BSS, + NUM_SEGMENTS +}; + +/* Constants from Mach headers */ +#define MH_MAGIC 0xfeedface +#define MH_EXECUTE 2 +#define LC_SEGMENT 1 +#define LC_SYMTAB 2 +#define LC_UNIXTHREAD 5 + +#define CPU_TYPE_X86 7 +#define CPU_SUBTYPE_X86_ALL 3 +#define x86_THREAD_STATE32 1 +#define x86_THREAD_STATE32_COUNT 16 + +#define CPU_TYPE_POWERPC 18 +#define CPU_SUBTYPE_POWERPC_ALL 0 +#define PPC_THREAD_STATE 1 +#define PPC_THREAD_STATE_COUNT 40 + +#define VM_PROT_NONE 0x0 +#define VM_PROT_READ 0x1 +#define VM_PROT_WRITE 0x2 +#define VM_PROT_EXECUTE 0x4 + +/* sizes of Mach structs */ +#define SZ_MACH_HEADER 28 +#define SZ_SEGMENT_COMMAND 56 +#define SZ_SECTION_HEADER 68 +#define SZ_SYMTAB_COMMAND 24 +#define SZ_THREAD_COMMAND_BF_STATE 16 +#define SZ_NLIST 12 + +/* the page size for x86 and PowerPC */ +#define CV_PGSZ 4096 +/* u modulo page size */ +#define pg_mod(u) ((u) & (CV_PGSZ - 1)) +/* u rounded down to whole pages */ +#define pg_trunc(u) ((u) & ~(CV_PGSZ - 1)) +/* u rounded up to whole pages */ +#define pg_round(u) pg_trunc((u) + (CV_PGSZ - 1)) + +const char zero_pg[CV_PGSZ] = { 0 }; + +/* + * machseg[0]: __PAGEZERO with address 0, size CV_PGSZ + * machseg[1]: __TEXT for ack TEXT, ROM + * machseg[2]: __DATA for ack DATA, BSS + */ +struct { + const char *ms_name; + uint32_t ms_vmaddr; + uint32_t ms_vmsize; + uint32_t ms_fileoff; + uint32_t ms_filesize; + uint32_t ms_prot; + uint32_t ms_nsects; +} machseg[3] = { + "__PAGEZERO", 0, CV_PGSZ, 0, 0, VM_PROT_NONE, 0, + "__TEXT", 0, 0, 0, 0, VM_PROT_READ | VM_PROT_EXECUTE, 2, + "__DATA", 0, 0, 0, 0, VM_PROT_READ | VM_PROT_WRITE, 2, +}; + + +static void +usage(void) +{ + fprintf(stderr, "Usage: %s -m \n", + program); + exit(1); +} + +/* Produce an error message and exit. */ +static void +fatal(const char* s, ...) +{ + va_list ap; + + fprintf(stderr, "%s: ",program) ; + + va_start(ap, s); + vfprintf(stderr, s, ap); + va_end(ap); + + fprintf(stderr, "\n"); + + if (outputfile) + unlink(outputfile); + exit(1); +} + +void +rd_fatal(void) +{ + fatal("read error"); +} + +/* Returns n such that 2**n == a. */ +static uint32_t +log2u(uint32_t a) +{ + uint32_t n = 0; + while (a) { + a >>= 1; + n++; + } + return n - 1; +} + +/* Writes a byte. */ +static void +emit8(uint8_t value) +{ + writef(&value, 1, 1); +} + +/* Writes out a 16-bit value in the appropriate endianness. */ +static void +emit16(uint16_t value) +{ + unsigned char buffer[2]; + + if (bigendian) + { + buffer[0] = (value >> 8) & 0xFF; + buffer[1] = (value >> 0) & 0xFF; + } + else + { + buffer[1] = (value >> 8) & 0xFF; + buffer[0] = (value >> 0) & 0xFF; + } + + writef(buffer, 1, sizeof(buffer)); +} + +/* Writes out a 32-bit value in the appropriate endianness. */ +static void +emit32(uint32_t value) +{ + unsigned char buffer[4]; + + if (bigendian) + { + buffer[0] = (value >> 24) & 0xFF; + buffer[1] = (value >> 16) & 0xFF; + buffer[2] = (value >> 8) & 0xFF; + buffer[3] = (value >> 0) & 0xFF; + } + else + { + buffer[3] = (value >> 24) & 0xFF; + buffer[2] = (value >> 16) & 0xFF; + buffer[1] = (value >> 8) & 0xFF; + buffer[0] = (value >> 0) & 0xFF; + } + + writef(buffer, 1, sizeof(buffer)); +} + +/* Copies the contents of a section from the input stream + * to the output stream. */ +static void +emit_section(int section_nr) +{ + struct outsect *section = &outsect[section_nr]; + size_t blocksize; + uint32_t n = section->os_flen; + char buffer[BUFSIZ]; + + rd_outsect(section_nr); + while (n > 0) + { + blocksize = (n > BUFSIZ) ? BUFSIZ : n; + rd_emit(buffer, (long)blocksize); + writef(buffer, 1, blocksize); + n -= blocksize; + } + + /* Zero fill any remaining space. */ + n = section->os_size - section->os_flen; + while (n > 0) + { + blocksize = (n > sizeof(zero_pg)) ? sizeof(zero_pg) : n; + writef(zero_pg, 1, blocksize); + n -= blocksize; + } +} + +static void +emit_lc_segment(int i) +{ + uint32_t sz; + int flags, maxprot; + char namebuf[16]; + + if (i == 0) { + /* special values for __PAGEZERO */ + maxprot = VM_PROT_NONE; + flags = 4; /* SG_NORELOC */ + } else { + maxprot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE; + flags = 0; + } + + /* + * The size of this command includes the size of its section + * headers, see emit_section_header(). + */ + sz = SZ_SEGMENT_COMMAND + machseg[i].ms_nsects * SZ_SECTION_HEADER; + + /* Use strncpy() to pad namebuf with '\0' bytes. */ + strncpy(namebuf, machseg[i].ms_name, sizeof(namebuf)); + + emit32(LC_SEGMENT); /* command */ + emit32(sz); /* size of command */ + writef(namebuf, 1, sizeof(namebuf)); + emit32(machseg[i].ms_vmaddr); /* vm address */ + emit32(machseg[i].ms_vmsize); /* vm size */ + emit32(machseg[i].ms_fileoff); /* file offset */ + emit32(machseg[i].ms_filesize); /* file size */ + emit32(maxprot); /* max protection */ + emit32(machseg[i].ms_prot); /* initial protection */ + emit32(machseg[i].ms_nsects); /* number of Mach sections */ + emit32(flags); /* flags */ +} + +static void +emit_section_header(int ms, const char *name, int os) +{ + uint32_t fileoff, flags; + char namebuf[16]; + + switch (os) { + case TEXT: + /* S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS */ + flags = 0x80000400; + break; + case BSS: + flags = 0x1; /* S_ZEROFILL */ + break; + default: + flags = 0x0; /* S_REGULAR */ + break; + } + + if (os == BSS) + fileoff = 0; + else + fileoff = machseg[ms].ms_fileoff + + (outsect[os].os_base - machseg[ms].ms_vmaddr); + + /* name of Mach section */ + strncpy(namebuf, name, sizeof(namebuf)); + writef(namebuf, 1, sizeof(namebuf)); + /* name of Mach segment */ + strncpy(namebuf, machseg[ms].ms_name, sizeof(namebuf)); + writef(namebuf, 1, sizeof(namebuf)); + emit32(outsect[os].os_base); /* vm address */ + emit32(outsect[os].os_size); /* vm size */ + emit32(fileoff); /* file offset */ + emit32(log2u(outsect[os].os_lign)); /* alignment */ + emit32(0); /* offset of relocations */ + emit32(0); /* number of relocations */ + emit32(flags); /* flags */ + emit32(0); /* reserved */ + emit32(0); /* reserved */ +} + +static void +emit_lc_symtab(void) +{ + uint32_t off1, off2; + + /* Symbol table will be at next page after machseg[2]. */ + off1 = pg_round(machseg[2].ms_fileoff + machseg[2].ms_filesize); + /* String table will be after symbol table. */ + off2 = off1 + 12 * outhead.oh_nname; + + emit32(LC_SYMTAB); /* command */ + emit32(SZ_SYMTAB_COMMAND); /* size of command */ + emit32(off1); /* offset of symbol table */ + emit32(outhead.oh_nname); /* number of symbols */ + emit32(off2); /* offset of string table */ + emit32(1 + outhead.oh_nchar); /* size of string table */ +} + +static void +emit_lc_unixthread(void) +{ + int i, ireg, ts, ts_count; + + /* + * The thread state has ts_count registers. The ireg'th + * register holds the entry point. We can set other registers + * to zero. At execution time, the kernel will allocate a + * stack and set the stack pointer. + */ + switch (cpu_type) { + case CPU_TYPE_X86: + ireg = 10; /* eip */ + ts = x86_THREAD_STATE32; + ts_count = x86_THREAD_STATE32_COUNT; + break; + case CPU_TYPE_POWERPC: + ireg = 0; /* srr0 */ + ts = PPC_THREAD_STATE; + ts_count = PPC_THREAD_STATE_COUNT; + break; + } + + emit32(LC_UNIXTHREAD); /* command */ + emit32(sz_thread_command); /* size of command */ + emit32(ts); /* thread state */ + emit32(ts_count); /* thread state count */ + for (i = 0; i < ts_count; i++) { + if (i == ireg) + emit32(entry); + else + emit32(0); + } +} + +static void +emit_symbol(struct outname *np) +{ + uint32_t soff; + uint8_t type; + uint8_t sect; + uint16_t desc; + + if (np->on_type & S_STB) { + /* stab for debugger */ + type = np->on_type >> 8; + desc = np->on_desc; + } else { + desc = 0; + + switch (np->on_type & S_TYP) { + case S_UND: + type = 0x0; /* N_UNDF */ + break; + case S_ABS: + type = 0x2; /* N_ABS */ + break; + default: + type = 0xe; /* N_SECT */ + break; + } + + if (np->on_type & S_EXT) + type |= 0x1; /* N_EXT */ + } + + switch (np->on_type & S_TYP) { + case S_MIN + TEXT: + sect = 1; + break; + case S_MIN + ROM: + sect = 2; + break; + case S_MIN + DATA: + sect = 3; + break; + case S_MIN + BSS: + case S_MIN + NUM_SEGMENTS: + sect = 4; + break; + default: + sect = 0; /* NO_SECT */ + break; + } + + /* + * To find the symbol's name, ack.out uses an offset from the + * beginning of the file, but Mach-o uses an offset into the + * string table. Both formats use offset 0 for a symbol with + * no name. We will prepend a '\0' at offset 0, so every + * named symbol needs + 1. + */ + if (np->on_foff) + soff = np->on_foff - ack_off_char + 1; + else + soff = 0; + + emit32(soff); + emit8(type); + emit8(sect); + emit16(desc); + emit32(np->on_valu); +} + +static void +emit_symtab(void) +{ + struct outname *names, *np; + int i; + char *chars; + + /* Using calloc(a, b) to check if a * b would overflow. */ + names = calloc(outhead.oh_nname, sizeof(struct outname)); + if (!names) + fatal("out of memory"); + chars = malloc(outhead.oh_nchar); + if (!names || !chars) + fatal("out of memory"); + rd_name(names, outhead.oh_nname); + rd_string(chars, outhead.oh_nchar); + + ack_off_char = OFF_CHAR(outhead); + + /* Emit each symbol entry. */ + for (i = 0, np = names; i < outhead.oh_nname; i++, np++) + emit_symbol(np); + + /* + * Emit the string table. The first character of a Mach-o + * string table must be '\0', so we prepend a '\0'. + */ + emit8(0); + writef(chars, 1, outhead.oh_nchar); +} + + +int +main(int argc, char *argv[]) +{ + uint32_t end, pad[3], sz, sz_load_cmds; + int cpu_subtype, fd, mflag = 0; + + /* General housecleaning and setup. */ + output = stdout; + program = argv[0]; + + /* Read in and process any flags. */ + while ((argc > 1) && (argv[1][0] == '-')) { + switch (argv[1][1]) { + case 'm': /* machine cpu type */ + mflag = 1; + cpu_type = atoi(&argv[1][2]); + break; + case 'h': /* help */ + default: + usage(); + } + + argv++; + argc--; + } + + if (!mflag) + usage(); + + /* Check cpu type. */ + switch (cpu_type) { + case CPU_TYPE_X86: + bigendian = 0; + cpu_subtype = CPU_SUBTYPE_X86_ALL; + sz_thread_command = 4 * x86_THREAD_STATE32_COUNT; + break; + case CPU_TYPE_POWERPC: + bigendian = 1; + cpu_subtype = CPU_SUBTYPE_POWERPC_ALL; + sz_thread_command = 4 * PPC_THREAD_STATE_COUNT; + break; + default: + /* Can't emit LC_UNIXTHREAD for unknown cpu. */ + fatal("unknown cpu type -m%d", cpu_type); + } + sz_thread_command += SZ_THREAD_COMMAND_BF_STATE; + + /* Process the rest of the arguments. */ + switch (argc) { + case 1: /* No parameters --- read from stdin, write to stdout. */ + rd_fdopen(0); + break; + + case 3: /* Both input and output files specified. */ + /* Use mode 0777 to allow executing the output file. */ + fd = open(argv[2], O_CREAT | O_TRUNC | O_WRONLY, 0777); + if (fd < 0) + fatal("unable to open output file."); + output = fdopen(fd, "w"); + if (!output) + fatal("unable to open output file."); + outputfile = argv[2]; + /* FALLTHROUGH */ + + case 2: /* Input file specified. */ + if (! rd_open(argv[1])) + fatal("unable to open input file."); + break; + + default: + usage(); + } + + rd_ohead(&outhead); + if (BADMAGIC(outhead)) + fatal("Not an ack object file."); + if (outhead.oh_flags & HF_LINK) + fatal("Contains unresolved references."); + if (outhead.oh_nrelo > 0) + fprintf(stderr, "Warning: relocation information present."); + if (outhead.oh_nsect != NUM_SEGMENTS && + outhead.oh_nsect != NUM_SEGMENTS + 1 ) { + fatal("Input file must have %d sections, not %ld\n", + NUM_SEGMENTS, (long)outhead.oh_nsect); + } + + rd_sect(outsect, outhead.oh_nsect); + + /* + * machseg[1] will start at a page boundary and include the + * Mach header and load commands before ack TEXT and ROM. + * + * Find our entry point (immediately after the load commands) + * and check that TEXT begins there. + */ + machseg[1].ms_vmaddr = pg_trunc(outsect[TEXT].os_base); + sz_load_cmds = 3 * SZ_SEGMENT_COMMAND + 4 * SZ_SECTION_HEADER + + SZ_SYMTAB_COMMAND + sz_thread_command; + entry = machseg[1].ms_vmaddr + SZ_MACH_HEADER + sz_load_cmds; + if (entry != outsect[TEXT].os_base) { + fatal("text segment must have base 0x%lx, not 0x%lx" + "\n\t(suggest em_led -b0:0x%lx)", + (unsigned long)entry, + (unsigned long)outsect[TEXT].os_base, + (unsigned long)entry); + } + + /* Pad for alignment between TEXT and ROM. */ + sz = outsect[ROM].os_base - outsect[TEXT].os_base; + pad[0] = sz - outsect[TEXT].os_size; + if (sz < outsect[TEXT].os_size || pad[0] >= outsect[ROM].os_lign) + fatal("the rom segment must follow the text segment."); + + /* + * Pad between ROM and DATA such that we can map machseg[2] at + * a page boundary with DATA at its correct base address. + * + * For example, if ROM ends at 0x2bed and DATA begins at + * 0x3000, then we pad to the page boundary. If ROM ends at + * 0x2bed and DATA begins at 0x3bf0, then pad = 3 and we map + * the page twice, at both 0x2000 and 0x3000. + */ + end = outsect[ROM].os_base + outsect[ROM].os_size; + pad[1] = pg_mod(outsect[DATA].os_base - end); + + sz = end - machseg[1].ms_vmaddr; + machseg[1].ms_vmsize = machseg[1].ms_filesize = sz; + machseg[2].ms_vmaddr = pg_trunc(outsect[DATA].os_base); + machseg[2].ms_fileoff = pg_trunc(sz + pad[1]); + if (machseg[2].ms_vmaddr < end && + machseg[2].ms_vmaddr >= machseg[1].ms_vmaddr) + fatal("the data and rom segments are too close." + "\n\t(suggest em_led -a2:%d)", (int)CV_PGSZ); + + if (outsect[BSS].os_flen != 0) + fatal("the bss space contains initialized data."); + sz = outsect[BSS].os_base - outsect[DATA].os_base; + if (sz < outsect[DATA].os_size || + sz - outsect[DATA].os_size >= outsect[BSS].os_lign) + fatal("the bss segment must follow the data segment."); + + end = outsect[DATA].os_base + outsect[DATA].os_size; + machseg[2].ms_filesize = end - machseg[2].ms_vmaddr; + end = outsect[BSS].os_base + outsect[BSS].os_size; + machseg[2].ms_vmsize = end - machseg[2].ms_vmaddr; + + if (outhead.oh_nsect == NUM_SEGMENTS + 1) { + if (outsect[NUM_SEGMENTS].os_base != + outsect[BSS].os_base + outsect[BSS].os_size) + fatal("end segment must follow bss"); + if (outsect[NUM_SEGMENTS].os_size != 0) + fatal("end segment must be empty"); + } + + /* + * Pad to page boundary between BSS and symbol table. + * + * Also, some versions of Mac OS X refuse to load any + * executable smaller than 4096 bytes (1 page). + */ + pad[2] = pg_mod(-(uint32_t)machseg[2].ms_filesize); + + /* Emit the Mach header. */ + emit32(MH_MAGIC); /* magic */ + emit32(cpu_type); /* cpu type */ + emit32(cpu_subtype); /* cpu subtype */ + emit32(MH_EXECUTE); /* file type */ + emit32(5); /* number of load commands */ + emit32(sz_load_cmds); /* size of load commands */ + emit32(0); /* flags */ + + emit_lc_segment(0); + emit_lc_segment(1); + emit_section_header(1, "__text", TEXT); + emit_section_header(1, "__rom", ROM); + emit_lc_segment(2); + emit_section_header(2, "__data", DATA); + emit_section_header(2, "__bss", BSS); + emit_lc_symtab(); + emit_lc_unixthread(); + + /* Emit non-empty sections. */ + emit_section(TEXT); + writef(zero_pg, 1, pad[0]); + emit_section(ROM); + writef(zero_pg, 1, pad[1]); + emit_section(DATA); + + writef(zero_pg, 1, pad[2]); + emit_symtab(); + + if (ferror(output)) + fatal("write error"); + + return 0; +} diff --git a/plat/osx/include/ack/config.h b/plat/osx/include/ack/config.h new file mode 100644 index 000000000..9f58a3941 --- /dev/null +++ b/plat/osx/include/ack/config.h @@ -0,0 +1,14 @@ +/* $Source$ + * $State$ + * $Revision$ + */ + +#ifndef _ACK_CONFIG_H +#define _ACK_CONFIG_H + +/* We're providing a time() system call rather than wanting a wrapper around + * gettimeofday() in the libc. */ + +/* #define ACKCONF_TIME_IS_A_SYSCALL */ + +#endif diff --git a/plat/osx/include/build.lua b/plat/osx/include/build.lua new file mode 100644 index 000000000..ff7c87a4d --- /dev/null +++ b/plat/osx/include/build.lua @@ -0,0 +1,26 @@ +include("plat/build.lua") + +headermap = {} +packagemap = {} + +local function addheader(h) + headermap[h] = "plat/osx/include/"..h + packagemap["$(PLATIND)/osx/include/"..h] = "plat/osx/include/"..h +end + +addheader("ack/config.h") +addheader("sys/dirent.h") +addheader("sys/mman.h") +addheader("sys/stat.h") +addheader("sys/types.h") +addheader("unistd.h") + +acklibrary { + name = "headers", + hdrs = headermap +} + +installable { + name = "pkg", + map = packagemap +} diff --git a/plat/osx/include/sys/dirent.h b/plat/osx/include/sys/dirent.h new file mode 100644 index 000000000..073c84588 --- /dev/null +++ b/plat/osx/include/sys/dirent.h @@ -0,0 +1,17 @@ +#ifndef _SYS_DIRENT_H +#define _SYS_DIRENT_H + +#include + +struct dirent { + ino_t d_ino; + unsigned short d_reclen; + unsigned char d_type; + unsigned char d_namlen; +#define MAXNAMLEN 255 + char d_name[MAXNAMLEN + 1]; +}; + +int getdirentries(int, char *, int, long *); + +#endif diff --git a/plat/osx/include/sys/mman.h b/plat/osx/include/sys/mman.h new file mode 100644 index 000000000..5a844c4b6 --- /dev/null +++ b/plat/osx/include/sys/mman.h @@ -0,0 +1,20 @@ +#ifndef _SYS_MMAN_H +#define _SYS_MMAN_H + +#include + +#define MAP_FAILED ((void *)-1) + +#define PROT_NONE 0x00 +#define PROT_READ 0x01 +#define PROT_WRITE 0x02 +#define PROT_EXEC 0x04 + +#define MAP_PRIVATE 0x0002 +#define MAP_FIXED 0x0010 +#define MAP_ANON 0x1000 + +void *mmap(void *, size_t, int, int, int, off_t); +int mprotect(void *, size_t, int); + +#endif diff --git a/plat/osx/include/sys/stat.h b/plat/osx/include/sys/stat.h new file mode 100644 index 000000000..6cb24902f --- /dev/null +++ b/plat/osx/include/sys/stat.h @@ -0,0 +1,49 @@ +#ifndef _SYS_STAT_H +#define _SYS_STAT_H + +#include +#include /* for timespec */ + +struct stat { + dev_t st_dev; + ino_t st_ino; + mode_t st_mode; + nlink_t st_nlink; + uid_t st_uid; + gid_t st_gid; + dev_t st_rdev; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; +#define st_atime st_atim.tv_sec +#define st_mtime st_mtim.tv_sec +#define st_ctime st_ctim.tv_sec + /* + * XXX - We don't have 64-bit integers, so we only expose the + * lower 32 bits of 64-bit fields. We insert dummy fields for + * the higher 32 bits. + */ +#if defined(__i386) + off_t st_size; + off_t _st_size_hi; + blkcnt_t st_blocks; + blkcnt_t _st_blkcnt_hi; +#elif defined(__powerpc) + off_t _st_size_hi; + off_t st_size; + blkcnt_t _st_blkcnt_hi; + blkcnt_t st_blkcnt; +#else +#error unknown arch +#endif + blksize_t st_blksize; + unsigned int st_flags; + unsigned int st_gen; + unsigned int _st_spare[5]; +}; + +int fstat(int, struct stat *); +int lstat(const char *, struct stat *); +int stat(const char *, struct stat *); + +#endif diff --git a/plat/osx/include/sys/types.h b/plat/osx/include/sys/types.h new file mode 100644 index 000000000..b4561b7b3 --- /dev/null +++ b/plat/osx/include/sys/types.h @@ -0,0 +1,17 @@ +#ifndef _SYS_TYPES_H +#define _SYS_TYPES_H + +#include /* for off_t, ptrdiff_t, size_t */ + +typedef int blkcnt_t; /* XXX should have 64 bits */ +typedef int blksize_t; +typedef int dev_t; +typedef unsigned int gid_t; +typedef unsigned int ino_t; +typedef unsigned short mode_t; +typedef unsigned short nlink_t; +typedef int pid_t; +typedef ptrdiff_t ssize_t; +typedef unsigned int uid_t; + +#endif diff --git a/plat/osx/include/unistd.h b/plat/osx/include/unistd.h new file mode 100644 index 000000000..bafa2a6c4 --- /dev/null +++ b/plat/osx/include/unistd.h @@ -0,0 +1,137 @@ +#ifndef _UNISTD_H +#define _UNISTD_H + +#include + +/* + * XXX - The following parts belong in other header files, + * but those headers are including us! + */ + +/* XXX - begin sys/ioctl.h */ + +#define TIOCGETD 0x4004741a + +int ioctl(int, unsigned long, ...); + +/* XXX - end sys/ioctl.h */ + +/* XXX - begin sys/time.h */ + +/* Don't conflict with time_t from */ +typedef long _libsys_time_t; +typedef int suseconds_t; + +struct timespec { + _libsys_time_t tv_sec; + long tv_nsec; +}; + +struct timeval { + _libsys_time_t tv_sec; + suseconds_t tv_usec; +}; + +struct timezone { + int tz_minuteswest; + int tz_dsttime; +}; + +int gettimeofday(struct timeval *, struct timezone *); + +/* XXX - end sys/time.h */ + +/* XXX - begin fcntl.h */ + +/* flags for open() */ +#define O_RDONLY 0x0000 +#define O_WRONLY 0x0001 +#define O_RDWR 0x0002 +#define O_NONBLOCK 0x0004 +#define O_APPEND 0x0008 +#define O_CREAT 0x0200 +#define O_TRUNC 0x0400 +#define O_EXCL 0x0800 + +int creat(const char *, mode_t); +int open(const char *, int, ...); + +/* XXX - end fcntl.h */ + +/* XXX - begin signal.h */ + +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGTRAP 5 +#define SIGABRT 6 +#define SIGEMT 7 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGBUS 10 +#define SIGSEGV 11 +#define SIGSYS 12 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGURG 16 +#define SIGSTOP 17 +#define SIGTSTP 18 +#define SIGCONT 19 +#define SIGCHLD 20 +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGIO 23 +#define SIGXCPU 24 +#define SIGXFSZ 25 +#define SIGVTALRM 26 +#define SIGPROF 27 +#define SIGWINCH 28 +#define SIGINFO 29 +#define SIGUSR1 30 +#define SIGUSR2 31 +#define _NSIG 32 + +/* sa_flags */ +#define SA_RESTART 0x0002 + +typedef void (*sig_t)(int); +#define SIG_DFL ((sig_t)0) +#define SIG_IGN ((sig_t)1) +#define SIG_ERR ((sig_t)-1) + +typedef unsigned int sigset_t; + +struct __siginfo; + +struct sigaction { + union { + void (*__sa_handler)(int); + void (*__sa_sigaction)(int, struct __siginfo *, void *); + } __sigaction_u; + sigset_t sa_mask; + int sa_flags; +}; +#define sa_handler __sigaction_u.__sa_handler +#define sa_sigaction __sigaction_u.__sa_sigaction + +int kill(pid_t, int); +int sigaction(int, const struct sigaction *, struct sigaction *); +sig_t signal(int, sig_t); + +int raise(int); /* in libc */ + +/* XXX - end signal.h */ + +void _exit(int); +int brk(void *); +int close(int); +pid_t getpid(void); +int isatty(int); +off_t lseek(int, off_t, int); +ssize_t read(int, void *, size_t); +void *sbrk(int); +ssize_t write(int, const void *, size_t); + +#endif diff --git a/plat/osx/libsys/brk.c b/plat/osx/libsys/brk.c new file mode 100644 index 000000000..9b58ca1d8 --- /dev/null +++ b/plat/osx/libsys/brk.c @@ -0,0 +1,86 @@ +/* + * This emulates brk() and sbrk() using mmap() and mprotect(). + * + * We reserve exactly SEGMENTSZ bytes of address space by calling + * mmap() with PROT_NONE. Then we allocate pages in our segment by + * calling mprotect() with PROT_READ|PROT_WRITE. + * + * This emulation can't resize its segment. If SEGMENTSZ is too big, + * then programs might run out of address space for other mappings. + */ +#include +#include +#include + +/* + * PAGESZ must be correct for this system! + * SEGMENTSZ must be a multiple of PAGESZ. + */ +#define PAGESZ 0x1000 /* page size for i386, powerpc */ +#define SEGMENTSZ 0x20000000 + +static char *segment; +static char *cbreak; /* current break */ + +static void brk_init(void) +{ + /* + * Try exactly once to reserve our segment. If we fail, then + * segment == MAP_FAILED and we never try again. + */ + if (segment == NULL) { + segment = mmap(NULL, SEGMENTSZ, PROT_NONE, + MAP_PRIVATE|MAP_ANON, -1, 0); + cbreak = segment; + } +} + +static int brk1(char *nbreak) +{ + size_t sz; + char *new, *old; + + sz = (segment == MAP_FAILED) ? 0 : SEGMENTSZ; + if (nbreak < segment || nbreak > segment + sz) { + errno = ENOMEM; + return -1; + } + + /* Round up to page size. */ + old = (char *)(((size_t)cbreak + (PAGESZ-1)) & ~(PAGESZ-1)); + new = (char *)(((size_t)nbreak + (PAGESZ-1)) & ~(PAGESZ-1)); + + if (new > old) { + /* Allocate pages by unprotecting them. */ + if (mprotect(old, new - old, PROT_READ|PROT_WRITE) < 0) { + errno = ENOMEM; + return -1; + } + } else if (new < old) { + /* + * Free pages by using MAP_FIXED to replace the + * mapping. Ignore errors. + */ + mmap(new, old - new, PROT_NONE, + MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0); + } + cbreak = nbreak; + return 0; +} + +int brk(void *addr) +{ + brk_init(); + return brk1(addr); +} + +void *sbrk(int incr) +{ + char *base; + + brk_init(); + base = cbreak; + if (brk1(base + incr) < 0) + return (void*)-1; + return base; +} diff --git a/plat/osx/libsys/creat.c b/plat/osx/libsys/creat.c new file mode 100644 index 000000000..3a350e357 --- /dev/null +++ b/plat/osx/libsys/creat.c @@ -0,0 +1,6 @@ +#include + +int creat(const char *path, mode_t mode) +{ + return open(path, O_CREAT | O_TRUNC | O_WRONLY, mode); +} diff --git a/plat/osx/libsys/isatty.c b/plat/osx/libsys/isatty.c new file mode 100644 index 000000000..1da6509df --- /dev/null +++ b/plat/osx/libsys/isatty.c @@ -0,0 +1,7 @@ +#include + +int isatty(int fd) +{ + int line_disc; + return 0 <= ioctl(fd, TIOCGETD, &line_disc); +} diff --git a/plat/osx/libsys/signal.c b/plat/osx/libsys/signal.c new file mode 100644 index 000000000..0c1e12624 --- /dev/null +++ b/plat/osx/libsys/signal.c @@ -0,0 +1,16 @@ +#include + +sig_t signal(int sig, sig_t func) +{ + struct sigaction newsa, oldsa; + int i; + + newsa.sa_handler = func; + newsa.sa_mask = 0; /* empty set */ + newsa.sa_flags = SA_RESTART; + + i = sigaction(sig, &newsa, &oldsa); + if (i < 0) + return SIG_ERR; + return oldsa.sa_handler; +} diff --git a/plat/osx386/README b/plat/osx386/README new file mode 100644 index 000000000..8c34134ff --- /dev/null +++ b/plat/osx386/README @@ -0,0 +1,25 @@ +The osx386 platform +=================== + + ack -mosx386 ... + +This platform produces Mach-o executables for Intel Mac OS X. These +are 32-bit executables using our i386 code generator. + +See ../osxppc/README, because our osx386 platform has many of the same +limitations and bugs as our osxppc platform. + + +Bugs +---- + +Some programs can't read the tty after using job control to suspend +and resume the program (with ^Z and "fg" in bash). The read(2) system +call fails with EINTR. In ACK's stdio (in libc), the error is sticky, +so all reads fail. In Apple's stdio, the error is not sticky, and +only the next read fails. The EINTR seems to happen only on Intel Mac +OS X, and not on other platforms. + + +George Koehler +2016-12-03 diff --git a/plat/osx386/boot.s b/plat/osx386/boot.s new file mode 100644 index 000000000..932a716e9 --- /dev/null +++ b/plat/osx386/boot.s @@ -0,0 +1,69 @@ +! plat/osx386/boot.s + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text + +begtext: + ! This code is placed at the entry point of the Mach-o + ! executable and is the first thing that runs. + ! + ! On entry, the stack looks like this: + ! + ! sp+.. NULL + ! sp+8+(4*argc) env (X quads) + ! sp+4+(4*argc) NULL + ! sp+4 argv (argc quads) + ! sp argc + ! + ! The ACK actually expects: + ! + ! sp+8 argc + ! sp+4 argv + ! sp env + + mov eax, (esp) ! eax = argc + lea ebx, 4(esp) ! ebx = argv + lea ecx, (esp)(eax*4) + add ecx, 12 ! environ + + push ecx ! environ + push ebx ! argc + push eax ! argv + push eax ! dummy, representing the return argument + xor ebp, ebp + + jmp __m_a_i_n + + ! This provides an emergency exit routine used by EM. + +.define EXIT +.extern EXIT +EXIT: + push 1 + jmp __exit + +.sect .rom +begrom: + +.sect .data +begdata: + +! Some magic data. All EM systems need these. + +.sect .bss +begbss: +.define hol0 +.comm hol0, 8 ! line number and filename (for debugging) + +.define _errno +.comm _errno, 4 ! Posix errno storage + +.define .trppc, .ignmask +.comm .trppc, 4 ! ptr to user trap handler +.comm .ignmask, 4 ! user trap ignore mask diff --git a/plat/osx386/build-pkg.lua b/plat/osx386/build-pkg.lua new file mode 100644 index 000000000..6dfe1561c --- /dev/null +++ b/plat/osx386/build-pkg.lua @@ -0,0 +1,24 @@ +include("plat/build.lua") + +ackfile { + name = "boot", + srcs = { "./boot.s" }, + vars = { plat = "osx386" } +} + +build_plat_libs { + name = "libs", + arch = "i386", + plat = "osx386", +} + +installable { + name = "pkg", + map = { + "+tools", + "+libs", + "plat/osx/include+pkg", + ["$(PLATIND)/osx386/boot.o"] = "+boot", + ["$(PLATIND)/osx386/libsys.a"] = "./libsys+lib", + } +} diff --git a/plat/osx386/build-tools.lua b/plat/osx386/build-tools.lua new file mode 100644 index 000000000..a1a9a8e2b --- /dev/null +++ b/plat/osx386/build-tools.lua @@ -0,0 +1,22 @@ +include("plat/build.lua") + +build_as { + name = "as", + arch = "i386", +} + +build_ncg { + name = "ncg", + arch = "i386", +} + +return installable { + name = "tools", + map = { + ["$(PLATDEP)/osx386/as"] = "+as", + ["$(PLATDEP)/osx386/ncg"] = "+ncg", + ["$(PLATIND)/descr/osx386"] = "./descr", + "plat/osx/cvmach+pkg", + "util/opt+pkg", + } +} diff --git a/plat/osx386/descr b/plat/osx386/descr new file mode 100644 index 000000000..afe46c588 --- /dev/null +++ b/plat/osx386/descr @@ -0,0 +1,81 @@ +# plat/osx386/descr + +var w=4 +var wa=4 +var p={w} +var pa={w} +var s=2 +var sa={s} +var l={w} +var la={w} +var f={w} +var fa={w} +var d=8 +var da={d} +var x=8 +var xa={x} +var ARCH=i386 +var PLATFORM=osx386 +var PLATFORMDIR={EM}/share/ack/{PLATFORM} +var CPP_F=-D__unix +var ALIGN=-a0:4 -a1:4 -a2:4096 -a3:4 -b0:0x123c +var C_LIB={PLATFORMDIR}/libc-ansi.a +# bitfields reversed for compatibility with (g)cc. +var CC_ALIGN=-Vr +var OLD_C_LIB={C_LIB} +var MACHOPT_F=-m10 +var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr + +# Override the setting in fe so that files compiled for osx386 can see +# the platform-specific headers. + +var C_INCLUDES=-I{EM}/share/ack/osx/include -I{EM}/share/ack/include/ansi + +name be + from .m.g + to .s + program {EM}/lib/ack/{PLATFORM}/ncg + mapflag -gdb GF=-gdb + args {GF?} < + stdout + need .e +end +name as + from .s.so + to .o + program {EM}/lib/ack/{PLATFORM}/as + args - -o > < + prep cond +end +name led + from .o.a + to .out + program {EM}/lib/ack/em_led + mapflag -l* LNAME={PLATFORMDIR}/lib* + mapflag -fp FLOATS={EM}/{LIB}fp + args {ALIGN} {SEPID?} \ + ({RTS}:.b=-u _i_main) \ + (.e:{HEAD}={PLATFORMDIR}/boot.o) \ + ({RTS}:.ocm.bas.b.c={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.mod={PLATFORMDIR}/modula2.o) \ + ({RTS}:.p={PLATFORMDIR}/pascal.o) \ + -o > < \ + (.b:{TAIL}={PLATFORMDIR}/libb.a) \ + (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ + (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ + (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ + (.p:{TAIL}={PLATFORMDIR}/libpascal.a) \ + (.ocm.bas.mod.b.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + {FLOATS?} \ + (.e:{TAIL}={PLATFORMDIR}/libem.a \ + {PLATFORMDIR}/libsys.a \ + {PLATFORMDIR}/libend.a) + linker +end +name cv + from .out + to .exe + program {EM}/lib/ack/cvmach + args -m7 < > + outfile osx386.exe +end diff --git a/plat/osx386/include/build.lua b/plat/osx386/include/build.lua new file mode 100644 index 000000000..c2a1050c2 --- /dev/null +++ b/plat/osx386/include/build.lua @@ -0,0 +1,4 @@ +installable { + name = "pkg", + map = { "plat/osx/include+pkg" } +} diff --git a/plat/osx386/libsys/_exit.s b/plat/osx386/libsys/_exit.s new file mode 100644 index 000000000..80d30134b --- /dev/null +++ b/plat/osx386/libsys/_exit.s @@ -0,0 +1,5 @@ +.sect .text +.define __exit +__exit: + mov eax, 1 + int 0x80 diff --git a/plat/osx386/libsys/build.lua b/plat/osx386/libsys/build.lua new file mode 100644 index 000000000..23e491f7a --- /dev/null +++ b/plat/osx386/libsys/build.lua @@ -0,0 +1,35 @@ +acklibrary { + name = "lib", + srcs = { + "./_exit.s", + "./close.s", + "./fstat.s", + "./getdirentries.s", + "./getpid.s", + "./gettimeofday.s", + "./ioctl.s", + "./kill.s", + "./lseek.s", + "./lstat.s", + "./mmap.s", + "./mprotect.s", + "./open.s", + "./read.s", + "./set_errno.s", + "./sigaction.s", + "./stat.s", + "./write.s", + "plat/linux/libsys/errno.s", + "plat/osx/libsys/brk.c", + "plat/osx/libsys/creat.c", + "plat/osx/libsys/isatty.c", + "plat/osx/libsys/signal.c", + }, + deps = { + "lang/cem/libcc.ansi/headers+headers", + "plat/osx386/include+pkg", + }, + vars = { + plat = "osx386" + } +} diff --git a/plat/osx386/libsys/close.s b/plat/osx386/libsys/close.s new file mode 100644 index 000000000..295b90ad1 --- /dev/null +++ b/plat/osx386/libsys/close.s @@ -0,0 +1,7 @@ +.sect .text +.define _close +_close: + mov eax, 6 + int 0x80 + jb .set_errno + ret diff --git a/plat/osx386/libsys/fstat.s b/plat/osx386/libsys/fstat.s new file mode 100644 index 000000000..1b49ae0b7 --- /dev/null +++ b/plat/osx386/libsys/fstat.s @@ -0,0 +1,7 @@ +.sect .text +.define _fstat +_fstat: + mov eax, 189 + int 0x80 + jb .set_errno + ret diff --git a/plat/osx386/libsys/getdirentries.s b/plat/osx386/libsys/getdirentries.s new file mode 100644 index 000000000..9c59c627c --- /dev/null +++ b/plat/osx386/libsys/getdirentries.s @@ -0,0 +1,7 @@ +.sect .text +.define _getdirentries +_getdirentries: + mov eax, 196 + int 0x80 + jb .set_errno + ret diff --git a/plat/osx386/libsys/getpid.s b/plat/osx386/libsys/getpid.s new file mode 100644 index 000000000..150791bb4 --- /dev/null +++ b/plat/osx386/libsys/getpid.s @@ -0,0 +1,7 @@ +.sect .text +.define _getpid +_getpid: + mov eax, 20 + int 0x80 + jb .set_errno + ret diff --git a/plat/osx386/libsys/gettimeofday.s b/plat/osx386/libsys/gettimeofday.s new file mode 100644 index 000000000..43aff5fa9 --- /dev/null +++ b/plat/osx386/libsys/gettimeofday.s @@ -0,0 +1,18 @@ +! The system call checks the timeval pointer but doesn't store the +! time there. If the pointer wasn't NULL, then the system call +! returns the time in a pair of registers. + +.sect .text +.define _gettimeofday +_gettimeofday: + mov eax, 116 + int 0x80 + jb .set_errno + mov ebx, 4(esp) ! timeval pointer + test ebx, ebx + je 1f + mov 0(ebx), eax ! seconds + mov 4(ebx), edx ! microseconds +1: + mov eax, 0 ! return 0 + ret diff --git a/plat/osx386/libsys/ioctl.s b/plat/osx386/libsys/ioctl.s new file mode 100644 index 000000000..5b13e2cfb --- /dev/null +++ b/plat/osx386/libsys/ioctl.s @@ -0,0 +1,7 @@ +.sect .text +.define _ioctl +_ioctl: + mov eax, 54 + int 0x80 + jb .set_errno + ret diff --git a/plat/osx386/libsys/kill.s b/plat/osx386/libsys/kill.s new file mode 100644 index 000000000..8fdce95fd --- /dev/null +++ b/plat/osx386/libsys/kill.s @@ -0,0 +1,7 @@ +.sect .text +.define _kill +_kill: + mov eax, 37 + int 0x80 + jb .set_errno + ret diff --git a/plat/osx386/libsys/lseek.s b/plat/osx386/libsys/lseek.s new file mode 100644 index 000000000..22543b2eb --- /dev/null +++ b/plat/osx386/libsys/lseek.s @@ -0,0 +1,17 @@ +.sect .text +.define _lseek +_lseek: + ! ack passes 4-byte off_t, but system call takes 8-byte off_t + mov eax, esp + push 12(eax) ! whence + push 0 ! offset (high long) + push 8(eax) ! offset (low long) + push 4(eax) ! fd + call 1f + add esp, 16 + ret +1: + mov eax, 199 + int 0x80 + jb .set_errno + ret diff --git a/plat/osx386/libsys/lstat.s b/plat/osx386/libsys/lstat.s new file mode 100644 index 000000000..a492cc3cb --- /dev/null +++ b/plat/osx386/libsys/lstat.s @@ -0,0 +1,7 @@ +.sect .text +.define _lstat +_lstat: + mov eax, 190 + int 0x80 + jb .set_errno + ret diff --git a/plat/osx386/libsys/mmap.s b/plat/osx386/libsys/mmap.s new file mode 100644 index 000000000..e39ea777a --- /dev/null +++ b/plat/osx386/libsys/mmap.s @@ -0,0 +1,20 @@ +.sect .text +.define _mmap +_mmap: + ! ack passes 4-byte off_t, but system call takes 8-byte off_t + mov eax, esp + push 0 ! offset (high long) + push 24(eax) ! offset (low long) + push 20(eax) ! fd + push 16(eax) ! flags + push 12(eax) ! protection + push 8(eax) ! length + push 4(eax) ! address + call 1f + add esp, 28 + ret +1: + mov eax, 197 + int 0x80 + jb .set_errno + ret diff --git a/plat/osx386/libsys/mprotect.s b/plat/osx386/libsys/mprotect.s new file mode 100644 index 000000000..641173a16 --- /dev/null +++ b/plat/osx386/libsys/mprotect.s @@ -0,0 +1,7 @@ +.sect .text +.define _mprotect +_mprotect: + mov eax, 74 + int 0x80 + jb .set_errno + ret diff --git a/plat/osx386/libsys/open.s b/plat/osx386/libsys/open.s new file mode 100644 index 000000000..154c00506 --- /dev/null +++ b/plat/osx386/libsys/open.s @@ -0,0 +1,7 @@ +.sect .text +.define _open +_open: + mov eax, 5 + int 0x80 + jb .set_errno + ret diff --git a/plat/osx386/libsys/read.s b/plat/osx386/libsys/read.s new file mode 100644 index 000000000..ccd3f8162 --- /dev/null +++ b/plat/osx386/libsys/read.s @@ -0,0 +1,7 @@ +.sect .text +.define _read +_read: + mov eax, 3 + int 0x80 + jb .set_errno + ret diff --git a/plat/osx386/libsys/set_errno.s b/plat/osx386/libsys/set_errno.s new file mode 100644 index 000000000..ff0823483 --- /dev/null +++ b/plat/osx386/libsys/set_errno.s @@ -0,0 +1,6 @@ +.sect .text +.define .set_errno +.set_errno: + mov (_errno), eax + mov eax, -1 + ret diff --git a/plat/osx386/libsys/sigaction.s b/plat/osx386/libsys/sigaction.s new file mode 100644 index 000000000..2909cbe02 --- /dev/null +++ b/plat/osx386/libsys/sigaction.s @@ -0,0 +1,59 @@ +! OS X, unlike FreeBSD, requires us to provide our own signal +! trampoline. We must change the new action from a struct sigaction +! to a bigger struct that includes the trampoline. + +.sect .text +.define _sigaction +_sigaction: + mov eax, esp + mov ebx, 8(esp) ! ebx = ptr to new action + cmp ebx, 0 + je 1f + ! push bigger struct + push 8(ebx) ! sa_flags + push 4(ebx) ! sa_mask + push trampoline ! sa_tramp + push 0(ebx) ! sa_handler + mov ebx, esp + jmp 2f +1: + sub esp, 16 +2: + push 12(eax) ! ptr to old action + push ebx ! ptr to bigger struct + push 4(eax) ! sig + call 3f + add esp, 28 + ret +3: + mov eax, 46 + int 0x80 + jb .set_errno + ret + +trampoline: + ! 4(esp) = handler + ! 8(esp) = info style + ! 12(esp) = sig + ! 16(esp) = info + ! 20(esp) = context + + ! Call handler(sig, info, context) + mov eax, esp + push 20(eax) + push 16(eax) + push 12(eax) + call 4(eax) + add esp, 12 + + ! Return from trampoline. + mov eax, esp + push 8(eax) ! info style + push 20(eax) ! context + sub esp, 4 + mov eax, 184 ! sigreturn + int 0x80 + + ! Only if sigreturn() fails: + mov eax, 1 ! exit + int 0x80 diff --git a/plat/osx386/libsys/stat.s b/plat/osx386/libsys/stat.s new file mode 100644 index 000000000..858d84db0 --- /dev/null +++ b/plat/osx386/libsys/stat.s @@ -0,0 +1,7 @@ +.sect .text +.define _stat +_stat: + mov eax, 188 + int 0x80 + jb .set_errno + ret diff --git a/plat/osx386/libsys/write.s b/plat/osx386/libsys/write.s new file mode 100644 index 000000000..a32d4d78a --- /dev/null +++ b/plat/osx386/libsys/write.s @@ -0,0 +1,7 @@ +.sect .text +.define _write +_write: + mov eax, 4 + int 0x80 + jb .set_errno + ret diff --git a/plat/osxppc/README b/plat/osxppc/README new file mode 100644 index 000000000..dd9a4d49c --- /dev/null +++ b/plat/osxppc/README @@ -0,0 +1,110 @@ +The osxppc platform +=================== + + ack -mosxppc ... + +This platform produces Mach-o executables for PowerPC Mac OS X. You +can run them from the command line in the Terminal. + +You *can't* link to libraries from other compilers. These static +executables don't use the dynamic linker. They don't load Apple's +libraries, so they can't call Carbon or Cocoa. + +The executables use BSD system calls to interact with your Mac. Our +libsys provides only a few system calls, enough to run a few demo +programs, but not much else. Check the header files in ../osx/include +for the available system calls. + + +Bugs +---- + +ACK didn't run on Mac OS X when this platform was added. The only way +to run ack -mosxppc was as a cross compiler from another operating +system. + +ACK doesn't have 64-bit integers, but Mac OS X uses 64-bit integers in +its system calls. Our libsys converts between 32-bit and 64-bit +integers by setting the high bits to zero, or discarding the high +bits. This affects lseek() and stat(). They report the wrong values +for file sizes and offsets beyond 4 gigabytes. + +Our PowerPC code generator is new and probably has bugs. Its stack +layout and calling conventions are not compatible with other +compilers. It passes all function arguments on the stack, which is +slower than passing them in registers. + + +Example +------- +Compile something: + + ack -mosxppc -O6 -o paranoia examples/paranoia.c + +The executable has a symbol table. If you have Apple's Xcode, try + + nm -g paranoia # to list the global symbols + otool -hl paranoia # to check the Mach header and load commands + gdb paranoia # to debug it + +Within gdb, commands like "gdb main" and "gdb '.ret'" can disassemble +functions. Backtraces don't work, because our stack layout is not the +same as Apple's. + + +Other hints +----------- + +PowerPC Macs became obsolete after Apple's transition to Intel. Mac +OS X 10.5 Leopard was the last version to run on PowerPC. The older +Mac OS X 10.4 Tiger was the last version to include Classic for +running Mac OS 9 programs. Our ack -mosxppc began to produce +executables in 2016, about 7 years after Apple released Mac OS X 10.6 +Snow Leopard for Intel only. + +Apple's Xcode included tools like gcc and gdb. It also had manual +pages for some system calls, like getdirentries(2). Some system calls +are like FreeBSD, some are unique to OS X. If you want to learn how +to call write(2) or sigaction(2), then a manual page from another BSD +or Linux might be enough. + +Xcode 2.5 was the last version to run on Tiger. The "Xcode 2.5 +Developer Tools" were a 902.9 MB download from Apple. As of 2016, the +download required an Apple ID and was available at: + + https://developer.apple.com/download/more/ + +Older versions of Xcode came with Mac OS X. If your version of OS X +came with your Mac, /Applications/Installers might contain an Xcode +installer. If you upgraded OS X, your install DVD might have Xcode. + +The source code at https://opensource.apple.com/ might reveal more +about system calls. For 10.4.11.ppc, the kernel is in xnu-792.24.17, +and Libc is in Libc-391.2.10. These files might help: + + xnu*/bsd/kern/syscalls.master + master list of BSD system calls + xnu*/osfmk/kern/syscall_sw.c + master list of Mach traps + xnu*/bsd/kern/mach_loader.c + details about loading Mach-o executables + xnu*/bsd/dev/ppc/unix_signal.c + details about sending signals to processes + xnu*/bsd/sys/*.h + headers that Xcode installs as /usr/include/sys/*.h + xnu*/bsd/man/man2/*.2 + manual pages that Xcode installs as /usr/share/man/man2/*.2 + Libc*/ppc/sys/SYS.h + Libc*/ppc/sys/*.s + assembly code (in gas syntax) for making system calls + +The 10.4.11.ppc sources are wrong for Intel; use 10.4.11.x86 or 10.5 +or newer. 10.5 moved SYS.h to xnu*/libsyscall/custom/SYS.h + +The kernel maps a common page into every process, and Apple's Libc +uses the common page to speed up system calls like gettimeofday(2). +Our libsys does not use the common page. + + +George Koehler +2016-12-03 diff --git a/plat/osxppc/boot.s b/plat/osxppc/boot.s new file mode 100644 index 000000000..e96198eb4 --- /dev/null +++ b/plat/osxppc/boot.s @@ -0,0 +1,60 @@ +! boot.s for osxppc + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text + +begtext: + ! This code is placed at the entry point of the Mach-o + ! executable and is the first thing that runs. + ! + ! On entry, the stack looks like this: + ! + ! sp+... NULL + ! sp+8+(4*argc) env (X quads) + ! sp+4+(4*argc) NULL + ! sp+4 argv (argc quads) + ! sp argc + ! + ! The ACK actually expects: + ! + ! sp+8 argc + ! sp+4 ptr to argv + ! sp ptr to env + + lwz r3, 0(sp) ! r3 = argc + addi r4, sp, 4 ! r4 = argv + rlwinm r5, r3, 32-2, 2, 31 ! shift left 2 bits + add r5, r5, r4 + addi r5, r5, 8 ! r5 = env + + stwu r5, -4(sp) + stwu r4, -4(sp) + stwu r3, -4(sp) + + b __m_a_i_n + +.sect .rom +begrom: + +.sect .data +begdata: + +! Some magic data. All EM systems need these. + +.sect .bss +begbss: +.define hol0 +.comm hol0, 8 ! line number and filename (for debugging) + +.define _errno +.comm _errno, 4 ! Posix errno storage + +.define .trppc, .ignmask +.comm .trppc, 4 ! ptr to user trap handler +.comm .ignmask, 4 ! user trap ignore mask diff --git a/plat/osxppc/build-pkg.lua b/plat/osxppc/build-pkg.lua new file mode 100644 index 000000000..c94ad6ef0 --- /dev/null +++ b/plat/osxppc/build-pkg.lua @@ -0,0 +1,24 @@ +include("plat/build.lua") + +ackfile { + name = "boot", + srcs = { "./boot.s" }, + vars = { plat = "osxppc" } +} + +build_plat_libs { + name = "libs", + arch = "powerpc", + plat = "osxppc", +} + +installable { + name = "pkg", + map = { + "+tools", + "+libs", + "plat/osx/include+pkg", + ["$(PLATIND)/osxppc/boot.o"] = "+boot", + ["$(PLATIND)/osxppc/libsys.a"] = "./libsys+lib", + } +} diff --git a/plat/osxppc/build-tools.lua b/plat/osxppc/build-tools.lua new file mode 100644 index 000000000..eddeea85a --- /dev/null +++ b/plat/osxppc/build-tools.lua @@ -0,0 +1,28 @@ +include("plat/build.lua") + +build_as { + name = "as", + arch = "powerpc", +} + +build_ncg { + name = "ncg", + arch = "powerpc", +} + +build_top { + name = "top", + arch = "powerpc", +} + +return installable { + name = "tools", + map = { + ["$(PLATDEP)/osxppc/as"] = "+as", + ["$(PLATDEP)/osxppc/ncg"] = "+ncg", + ["$(PLATDEP)/osxppc/top"] = "+top", + ["$(PLATIND)/descr/osxppc"] = "./descr", + "plat/osx/cvmach+pkg", + "util/opt+pkg", + } +} diff --git a/plat/osxppc/descr b/plat/osxppc/descr new file mode 100644 index 000000000..5f416c44c --- /dev/null +++ b/plat/osxppc/descr @@ -0,0 +1,86 @@ +# plat/osxppc/descr + +var w=4 +var wa=4 +var p={w} +var pa={w} +var s=2 +var sa={s} +var l={w} +var la={w} +var f={w} +var fa={w} +var d=8 +var da={d} +var x=8 +var xa={x} +var ARCH=powerpc +var PLATFORM=osxppc +var PLATFORMDIR={EM}/share/ack/{PLATFORM} +var CPP_F=-D__unix +var ALIGN=-a0:4 -a1:4 -a2:4096 -a3:4 -b0:0x129c +var MACHOPT_F=-m3 +var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr + +# Override the setting in fe so that files compiled for osxppc can see +# the platform-specific headers. + +var C_INCLUDES=-I{EM}/share/ack/osx/include -I{EM}/share/ack/include/ansi + +name be + from .m.g + to .s + program {EM}/lib/ack/{PLATFORM}/ncg + mapflag -gdb GF=-gdb + args {GF?} < + stdout + need .e +end +name asopt + from .s + to .so + program {EM}/lib/ack/{PLATFORM}/top + args + optimizer + stdin + stdout +end +name as + from .s.so + to .o + program {EM}/lib/ack/{PLATFORM}/as + args - -o > < + prep cond +end +name led + from .o.a + to .out + program {EM}/lib/ack/em_led + mapflag -l* LNAME={PLATFORMDIR}/lib* + mapflag -fp FLOATS={EM}/{LIB}fp + args {ALIGN} {SEPID?} \ + ({RTS}:.b=-u _i_main) \ + (.e:{HEAD}={PLATFORMDIR}/boot.o) \ + ({RTS}:.ocm.bas.b.c={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.mod={PLATFORMDIR}/modula2.o) \ + ({RTS}:.p={PLATFORMDIR}/pascal.o) \ + -o > < \ + (.b:{TAIL}={PLATFORMDIR}/libb.a) \ + (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ + (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ + (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ + (.p:{TAIL}={PLATFORMDIR}/libpascal.a) \ + (.ocm.bas.mod.b.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + {FLOATS?} \ + (.e:{TAIL}={PLATFORMDIR}/libem.a \ + {PLATFORMDIR}/libsys.a \ + {PLATFORMDIR}/libend.a) + linker +end +name cv + from .out + to .exe + program {EM}/lib/ack/cvmach + args -m18 < > + outfile osxppc.exe +end diff --git a/plat/osxppc/include/build.lua b/plat/osxppc/include/build.lua new file mode 100644 index 000000000..0fe204ece --- /dev/null +++ b/plat/osxppc/include/build.lua @@ -0,0 +1,4 @@ +installable { + name = "pkg", + map = { "plat/osx/include+pkg" } +} \ No newline at end of file diff --git a/plat/osxppc/libsys/_exit.s b/plat/osxppc/libsys/_exit.s new file mode 100644 index 000000000..6ffe502d5 --- /dev/null +++ b/plat/osxppc/libsys/_exit.s @@ -0,0 +1,6 @@ +.sect .text +.define __exit +__exit: + addi r0, r0, 1 ! _exit + lwz r3, 0(sp) ! status + sc 0 diff --git a/plat/osxppc/libsys/build.lua b/plat/osxppc/libsys/build.lua new file mode 100644 index 000000000..072730b7a --- /dev/null +++ b/plat/osxppc/libsys/build.lua @@ -0,0 +1,35 @@ +acklibrary { + name = "lib", + srcs = { + "./_exit.s", + "./close.s", + "./fstat.s", + "./getdirentries.s", + "./getpid.s", + "./gettimeofday.s", + "./ioctl.s", + "./kill.s", + "./lseek.s", + "./lstat.s", + "./mmap.s", + "./mprotect.s", + "./open.s", + "./read.s", + "./set_errno.s", + "./sigaction.s", + "./stat.s", + "./write.s", + "plat/linuxppc/libsys/trap.s", + "plat/osx/libsys/brk.c", + "plat/osx/libsys/creat.c", + "plat/osx/libsys/isatty.c", + "plat/osx/libsys/signal.c", + }, + deps = { + "lang/cem/libcc.ansi/headers+headers", + "plat/osxppc/include+pkg", + }, + vars = { + plat = "osxppc" + } +} diff --git a/plat/osxppc/libsys/close.s b/plat/osxppc/libsys/close.s new file mode 100644 index 000000000..a799b5e9d --- /dev/null +++ b/plat/osxppc/libsys/close.s @@ -0,0 +1,8 @@ +.sect .text +.define _close +_close: + addi r0, r0, 6 ! close + lwz r3, 0(sp) ! fd + sc 0 + b .set_errno + bclr 20, 0, 0 diff --git a/plat/osxppc/libsys/fstat.s b/plat/osxppc/libsys/fstat.s new file mode 100644 index 000000000..d641cbd91 --- /dev/null +++ b/plat/osxppc/libsys/fstat.s @@ -0,0 +1,9 @@ +.sect .text +.define _fstat +_fstat: + addi r0, r0, 189 ! fstat + lwz r3, 0(sp) ! fd + lwz r4, 4(sp) ! stat pointer + sc 0 + b .set_errno + bclr 20, 0, 0 diff --git a/plat/osxppc/libsys/getdirentries.s b/plat/osxppc/libsys/getdirentries.s new file mode 100644 index 000000000..d038c5977 --- /dev/null +++ b/plat/osxppc/libsys/getdirentries.s @@ -0,0 +1,11 @@ +.sect .text +.define _getdirentries +_getdirentries: + addi r0, r0, 196 ! getdirentries + lwz r3, 0(sp) ! fd + lwz r4, 4(sp) ! buffer + lwz r5, 8(sp) ! buffer size + lwz r6, 12(sp) ! base pointer + sc 0 + b .set_errno + bclr 20, 0, 0 diff --git a/plat/osxppc/libsys/getpid.s b/plat/osxppc/libsys/getpid.s new file mode 100644 index 000000000..36525cf43 --- /dev/null +++ b/plat/osxppc/libsys/getpid.s @@ -0,0 +1,7 @@ +.sect .text +.define _getpid +_getpid: + addi r0, r0, 20 ! getpid + sc 0 + b .set_errno + bclr 20, 0, 0 diff --git a/plat/osxppc/libsys/gettimeofday.s b/plat/osxppc/libsys/gettimeofday.s new file mode 100644 index 000000000..178d17fdd --- /dev/null +++ b/plat/osxppc/libsys/gettimeofday.s @@ -0,0 +1,19 @@ +! The system call checks the timeval pointer but doesn't store the +! time there. If the pointer wasn't NULL, then the system call +! returns the time in a pair of registers. + +.sect .text +.define _gettimeofday +_gettimeofday: + addi r0, r0, 116 ! gettimeofday + lwz r3, 0(sp) ! timeval pointer + lwz r4, 4(sp) ! timezone pointer + or. r5, r3, r3 + sc 0 + b .set_errno + bc 12, 2, 1f ! beq 1f + stw r3, 0(r5) ! seconds + stw r4, 4(r5) ! microseconds +1: + addi r3, r0, 0 ! return 0 + bclr 20, 0, 0 diff --git a/plat/osxppc/libsys/ioctl.s b/plat/osxppc/libsys/ioctl.s new file mode 100644 index 000000000..685ba8499 --- /dev/null +++ b/plat/osxppc/libsys/ioctl.s @@ -0,0 +1,10 @@ +.sect .text +.define _ioctl +_ioctl: + addi r0, r0, 54 ! ioctl + lwz r3, 0(sp) ! fd + lwz r4, 4(sp) ! command + lwz r5, 8(sp) ! argument pointer + sc 0 + b .set_errno + bclr 20, 0, 0 diff --git a/plat/osxppc/libsys/kill.s b/plat/osxppc/libsys/kill.s new file mode 100644 index 000000000..4c7d5566f --- /dev/null +++ b/plat/osxppc/libsys/kill.s @@ -0,0 +1,9 @@ +.sect .text +.define _kill +_kill: + addi r0, r0, 37 ! kill + lwz r3, 0(sp) ! pid + lwz r4, 4(sp) ! signal + sc 0 + b .set_errno + bclr 20, 0, 0 diff --git a/plat/osxppc/libsys/lseek.s b/plat/osxppc/libsys/lseek.s new file mode 100644 index 000000000..129b08a8d --- /dev/null +++ b/plat/osxppc/libsys/lseek.s @@ -0,0 +1,13 @@ +.sect .text +.define _lseek +_lseek: + addi r0, r0, 199 ! lseek + lwz r3, 0(sp) ! fd + ! ack passes 4-byte off_t, but system call takes 8-byte off_t + addi r4, r0, 0 ! offset (high word) + lwz r5, 4(sp) ! offset (low word) + lwz r6, 8(sp) ! whence + sc 0 + b .set_errno + or r3, r4, r4 ! return offset (low word) + bclr 20, 0, 0 diff --git a/plat/osxppc/libsys/lstat.s b/plat/osxppc/libsys/lstat.s new file mode 100644 index 000000000..24d7c44ab --- /dev/null +++ b/plat/osxppc/libsys/lstat.s @@ -0,0 +1,9 @@ +.sect .text +.define _lstat +_lstat: + addi r0, r0, 190 ! lstat + lwz r3, 0(sp) ! path + lwz r4, 4(sp) ! stat pointer + sc 0 + b .set_errno + bclr 20, 0, 0 diff --git a/plat/osxppc/libsys/mmap.s b/plat/osxppc/libsys/mmap.s new file mode 100644 index 000000000..f2ec5e28b --- /dev/null +++ b/plat/osxppc/libsys/mmap.s @@ -0,0 +1,15 @@ +.sect .text +.define _mmap +_mmap: + addi r0, r0, 197 ! mmap + lwz r3, 0(sp) ! address + lwz r4, 4(sp) ! length + lwz r5, 8(sp) ! protection + lwz r6, 12(sp) ! flags + lwz r7, 16(sp) ! fd + ! ack passes 4-byte off_t, but system call takes 8-byte off_t + addi r8, r0, 0 ! offset (high word) + lwz r9, 20(sp) ! offset (low word) + sc 0 + b .set_errno + bclr 20, 0, 0 diff --git a/plat/osxppc/libsys/mprotect.s b/plat/osxppc/libsys/mprotect.s new file mode 100644 index 000000000..fbea70251 --- /dev/null +++ b/plat/osxppc/libsys/mprotect.s @@ -0,0 +1,10 @@ +.sect .text +.define _mprotect +_mprotect: + addi r0, r0, 74 ! mprotect + lwz r3, 0(sp) ! address + lwz r4, 4(sp) ! length + lwz r5, 8(sp) ! protection + sc 0 + b .set_errno + bclr 20, 0, 0 diff --git a/plat/osxppc/libsys/open.s b/plat/osxppc/libsys/open.s new file mode 100644 index 000000000..1d066c7ad --- /dev/null +++ b/plat/osxppc/libsys/open.s @@ -0,0 +1,10 @@ +.sect .text +.define _open +_open: + addi r0, r0, 5 ! open + lwz r3, 0(sp) ! path + lwz r4, 4(sp) ! flags + lwz r5, 8(sp) ! mode + sc 0 + b .set_errno + bclr 20, 0, 0 diff --git a/plat/osxppc/libsys/read.s b/plat/osxppc/libsys/read.s new file mode 100644 index 000000000..849da5932 --- /dev/null +++ b/plat/osxppc/libsys/read.s @@ -0,0 +1,10 @@ +.sect .text +.define _read +_read: + addi r0, r0, 3 ! read + lwz r3, 0(sp) ! fd + lwz r4, 4(sp) ! buffer + lwz r5, 8(sp) ! buffer size + sc 0 + b .set_errno + bclr 20, 0, 0 diff --git a/plat/osxppc/libsys/set_errno.s b/plat/osxppc/libsys/set_errno.s new file mode 100644 index 000000000..e406865a6 --- /dev/null +++ b/plat/osxppc/libsys/set_errno.s @@ -0,0 +1,7 @@ +.sect .text +.define .set_errno +.set_errno: + li32 r10, _errno + stw r3, 0(r10) ! set errno + addi r3, r0, -1 ! return -1 + bclr 20, 0, 0 diff --git a/plat/osxppc/libsys/sigaction.s b/plat/osxppc/libsys/sigaction.s new file mode 100644 index 000000000..f330c88a5 --- /dev/null +++ b/plat/osxppc/libsys/sigaction.s @@ -0,0 +1,59 @@ +#define IFTRUE 12 +#define ALWAYS 20 +#define EQ 2 + +! OS X, unlike FreeBSD, requires us to provide our own signal +! trampoline. We must change the new action from a struct sigaction +! to a bigger struct that includes the trampoline. + +.sect .text +.define _sigaction +_sigaction: + addi r0, r0, 46 ! sigaction + lwz r3, 0(sp) ! sig + lwz r4, 4(sp) ! ptr to new action + lwz r5, 8(sp) ! ptr to old action + or. r6, r4, r4 + bc IFTRUE, EQ, 1f ! skip if new action is NULL + + ! We may use the "red zone" from -224(sp) to 0(sp). + addi r4, sp, -16 ! r4 = bigger struct + lwz r7, 0(r6) + stw r7, 0(r4) ! sa_handler + li32 r7, trampoline + stw r7, 4(r4) ! sa_tramp + lwz r7, 4(r6) + stw r7, 8(r4) ! sa_mask + lwz r7, 8(r6) + stw r7, 12(r4) ! sa_flags +1: + sc 0 + b .set_errno + bclr 20, 0, 0 + +trampoline: + ! r3 = handler + ! r4 = info style + ! r5 = sig + ! r6 = info + ! r7 = context + or r31, r4, r4 ! ack preserves r30, r31 + or r30, r7, r7 + + ! Call handler(sig, info, context). + mtspr ctr, r3 + stwu r7, -4(sp) ! ack expects arguments on stack + stwu r6, -4(sp) + stwu r5, -4(sp) + bcctrl ALWAYS, 0, 0 + + ! Return from trampoline. + addi r0, r0, 184 ! sigreturn + or r3, r30, r30 ! context + or r4, r31, r31 ! info style + sc 0 + ori r0, r0, 0 ! nop + + ! Only if sigreturn() fails: + addi r0, r0, 1 ! exit + sc 0 diff --git a/plat/osxppc/libsys/stat.s b/plat/osxppc/libsys/stat.s new file mode 100644 index 000000000..ab8422cda --- /dev/null +++ b/plat/osxppc/libsys/stat.s @@ -0,0 +1,9 @@ +.sect .text +.define _stat +_stat: + addi r0, r0, 188 ! stat + lwz r3, 0(sp) ! path + lwz r4, 4(sp) ! stat pointer + sc 0 + b .set_errno + bclr 20, 0, 0 diff --git a/plat/osxppc/libsys/write.s b/plat/osxppc/libsys/write.s new file mode 100644 index 000000000..48f59cd72 --- /dev/null +++ b/plat/osxppc/libsys/write.s @@ -0,0 +1,10 @@ +.sect .text +.define _write +_write: + addi r0, r0, 4 ! write + lwz r3, 0(sp) ! fd + lwz r4, 4(sp) ! buffer + lwz r5, 8(sp) ! buffer size + sc 0 + b .set_errno + bclr 20, 0, 0 diff --git a/plat/pc86/README b/plat/pc86/README index 689c70844..dcbe0ba27 100644 --- a/plat/pc86/README +++ b/plat/pc86/README @@ -23,6 +23,9 @@ are stubs required to make the demo apps link. File descriptors 0, 1 and 2 represent the console. All reads block. There's enough TTY emulation to allow \n conversion and local echo (but it can't be turned off). +Console output is echoed to the serial port (without any setup). This is used +by qemu for running tests. + Example command line ==================== diff --git a/plat/pc86/boot.s b/plat/pc86/boot.s index 534809697..51b288e75 100644 --- a/plat/pc86/boot.s +++ b/plat/pc86/boot.s @@ -23,7 +23,7 @@ ! If you ever need to change the boot code, this needs adjusting. I recommend ! a hex editor. -PADDING = 0xB7 +PADDING = 0xB3 ! Some definitions. @@ -271,9 +271,12 @@ finished: ! Push standard parameters onto the stack and go. - push envp ! envp - push argv ! argv - push 1 ! argc + mov ax, envp + push ax + mov ax, argv + push ax + mov ax, 1 + push ax call __m_a_i_n ! fall through into the exit routine. diff --git a/plat/pc86/descr b/plat/pc86/descr index d8cb006e6..9b54410ff 100644 --- a/plat/pc86/descr +++ b/plat/pc86/descr @@ -20,7 +20,7 @@ var ARCH=i86 var PLATFORM=pc86 var PLATFORMDIR={EM}/share/ack/{PLATFORM} var CPP_F=-D__unix -var ALIGN=-a0:1 -a1:1 -a2:1 -a3:1 +var ALIGN=-a0:2 -a1:2 -a2:2 -a3:2 var MACHOPT_F=-m8 var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr @@ -52,17 +52,19 @@ name led mapflag -i SEPID=-b1:0 mapflag -fp FLOATS={EM}/{ILIB}fp args {ALIGN} {SEPID?} \ + ({RTS}:.b=-u _i_main) \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ - ({RTS}:.ocm.b={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.ocm.bas.b={PLATFORMDIR}/c-ansi.o) \ ({RTS}:.c={PLATFORMDIR}/c-ansi.o) \ ({RTS}:.mod={PLATFORMDIR}/modula2.o) \ ({RTS}:.p={PLATFORMDIR}/pascal.o) \ -o > < \ (.p:{TAIL}={PLATFORMDIR}/libpascal.a) \ - (.b:{TAIL}={PLATFORMDIR}/libbasic.a) \ + (.b:{TAIL}={PLATFORMDIR}/libb.a) \ + (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ - (.ocm.b.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + (.ocm.bas.mod.b.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ diff --git a/plat/pc86/include/unistd.h b/plat/pc86/include/unistd.h index ea4f51c0f..174c43ad0 100644 --- a/plat/pc86/include/unistd.h +++ b/plat/pc86/include/unistd.h @@ -37,6 +37,7 @@ extern char** environ; extern void _exit(int); extern pid_t getpid(void); +extern int brk(void* addr); extern void* sbrk(int increment); extern int isatty(int d); extern off_t lseek(int fildes, off_t offset, int whence); diff --git a/plat/pc86/libsys/_sys_rawwrite.s b/plat/pc86/libsys/_sys_rawwrite.s index 75f75aae1..ae477c6d2 100644 --- a/plat/pc86/libsys/_sys_rawwrite.s +++ b/plat/pc86/libsys/_sys_rawwrite.s @@ -21,9 +21,18 @@ __sys_rawwrite: push bp mov bp, sp + ! Write to the BIOS console. + movb al, 4(bp) movb ah, 0x0E mov bx, 0x0007 int 0x10 + + ! Also write to the serial port (used by the test suite). + + movb ah, 0x01 + xor dx, dx + int 0x14 + jmp .cret \ No newline at end of file diff --git a/plat/pc86/libsys/brk.c b/plat/pc86/libsys/brk.c index 952a9c747..293703234 100644 --- a/plat/pc86/libsys/brk.c +++ b/plat/pc86/libsys/brk.c @@ -22,7 +22,10 @@ int brk(void* newend) if ((p > (&dummy - STACK_BUFFER)) || (p < _end)) + { + errno = ENOMEM; return -1; + } current = p; return 0; @@ -31,13 +34,26 @@ int brk(void* newend) void* sbrk(int increment) { char* old; - + char* new; + if (increment == 0) return current; old = current; - if (brk(old + increment) < 0) - return OUT_OF_MEMORY; + + new = old + increment; + + if ((increment > 0) && (new <= old)) + goto out_of_memory; + else if ((increment < 0) && (new >= old)) + goto out_of_memory; + + if (brk(new) < 0) + goto out_of_memory; return old; + +out_of_memory: + errno = ENOMEM; + return OUT_OF_MEMORY; } diff --git a/plat/pc86/tests/build.lua b/plat/pc86/tests/build.lua new file mode 100644 index 000000000..fe871e450 --- /dev/null +++ b/plat/pc86/tests/build.lua @@ -0,0 +1,7 @@ +include("tests/plat/build.lua") + +plat_testsuite { + name = "tests", + plat = "pc86", + method = "qemu-system-i386" +} diff --git a/plat/qemuppc/boot.s b/plat/qemuppc/boot.s index 2dd9a4c5c..ac3227dc9 100644 --- a/plat/qemuppc/boot.s +++ b/plat/qemuppc/boot.s @@ -13,22 +13,14 @@ .sect .text begtext: - ! This code is placed at the beginning of the ELF executable and is the - ! first thing that runs. + ! This code is the first thing that runs. The booloader + ! passes the Open Firmware pointer in r5. ! - ! On entry, the stack looks like this: + ! We keep the bootloader's stack. The ACK expects: ! - ! sp+... NULL - ! sp+8+(4*argc) env (X quads) - ! sp+4+(4*argc) NULL - ! sp+4 argv (argc quads) + ! sp+8 environment pointer + ! sp+4 argv as a pointer ! sp argc - ! - ! The ACK actually expects: - ! - ! sp+8 argc - ! sp+4 ptr to argv - ! sp ptr to env li32 r3, __openfirmware_ptr stw r5, 0(r3) @@ -47,15 +39,23 @@ begtext: ! falls through .define __exit -.extern __exit .define EXIT -.extern EXIT __exit: EXIT: - b EXIT + ! Halt the CPU. This code halts the default G3 emulation of + ! qemu-system-ppc. It's wrong for some other CPU models. +#define hid0 0x3f0 +#define mfmsr(r) [[31<<26]|[[r]<<21]|0x0a6] +#define mtmsr(r) [[31<<26]|[[r]<<21]|0x124] + mfspr r3, hid0 + oris r3, r3, 0x00e0 ! set DOZE, NAP, SLEEP + mtspr hid0, r3 ! in hid0 + .data4 mfmsr(3) + oris r3, r3, 0x0004 ! set POW + .data4 mtmsr(3) ! in msr + b EXIT ! If we failed to halt, then spin. .define _openfirmware_call -.extern _openfirmware_call _openfirmware_call: lwz r3, 0(sp) li32 r4, __openfirmware_ptr @@ -66,15 +66,10 @@ _openfirmware_call: ! Define symbols at the beginning of our various segments, so that we can find ! them. (Except .text, which has already been done.) -.sect .data; begdata: .sect .rom; begrom: +.sect .data; begdata: .sect .bss; begbss: -! Some magic data. All EM systems need these. - -.define _errno -.comm _errno, 4 ! Posix errno storage - ! The argv and env arrays. .sect .rom @@ -82,6 +77,12 @@ argv: .data4 exename, 0 envp: .data4 0 exename: .asciz 'qemuppc.img' +! Some magic data. All EM systems need these. + +.sect .bss +.define _errno +.comm _errno, 4 ! Posix errno storage + .define .trppc, .ignmask .comm .trppc, 4 ! ptr to user trap handler .comm .ignmask, 4 ! user trap ignore mask diff --git a/plat/qemuppc/descr b/plat/qemuppc/descr index c0bc1eab0..f5191b249 100644 --- a/plat/qemuppc/descr +++ b/plat/qemuppc/descr @@ -62,17 +62,19 @@ name led mapflag -l* LNAME={PLATFORMDIR}/lib* mapflag -fp FLOATS={EM}/{LIB}fp args {ALIGN} {SEPID?} \ + ({RTS}:.b=-u _i_main) \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ - ({RTS}:.ocm.b={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.ocm.bas.b={PLATFORMDIR}/c-ansi.o) \ ({RTS}:.c={PLATFORMDIR}/c-ansi.o) \ ({RTS}:.mod={PLATFORMDIR}/modula2.o) \ ({RTS}:.p={PLATFORMDIR}/pascal.o) \ -o > < \ (.p:{TAIL}={PLATFORMDIR}/libpascal.a) \ - (.b:{TAIL}={PLATFORMDIR}/libbasic.a) \ + (.b:{TAIL}={PLATFORMDIR}/libb.a) \ + (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ - (.ocm.b.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + (.ocm.bas.mod.b.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ diff --git a/plat/qemuppc/libsys/brk.c b/plat/qemuppc/libsys/brk.c index 118bda3cf..7d49fa960 100644 --- a/plat/qemuppc/libsys/brk.c +++ b/plat/qemuppc/libsys/brk.c @@ -34,13 +34,26 @@ int brk(void* newend) void* sbrk(int increment) { char* old; + char* new; if (increment == 0) return current; old = current; - if (brk(old + increment) < 0) - return OUT_OF_MEMORY; + + new = old + increment; + + if ((increment > 0) && (new <= old)) + goto out_of_memory; + else if ((increment < 0) && (new >= old)) + goto out_of_memory; + + if (brk(new) < 0) + goto out_of_memory; return old; + +out_of_memory: + errno = ENOMEM; + return OUT_OF_MEMORY; } diff --git a/plat/qemuppc/libsys/trap.s b/plat/qemuppc/libsys/trap.s index f05b907d0..e00c4d561 100644 --- a/plat/qemuppc/libsys/trap.s +++ b/plat/qemuppc/libsys/trap.s @@ -49,21 +49,17 @@ EUNIMPL = 63 ! unimplemented em-instruction called .define .trap_ecase .trap_ecase: b .trp - + .define .trap_earray .trap_earray: b .trp +.define .trap_erange +.trap_erange: + b .trap + .define .trp .define .trap .trp: .trap: b .trp ! spin forever - -.define .sig -.sig: - lwz r3, 0(sp) - li32 r4, .trppc - stw r3, 0(r4) - bclr ALWAYS, 0, 0 ! return - \ No newline at end of file diff --git a/plat/qemuppc/tests/brk_c.c b/plat/qemuppc/tests/brk_c.c deleted file mode 100644 index aa0f7ef99..000000000 --- a/plat/qemuppc/tests/brk_c.c +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include -#include -#include -#include -#include "test.h" - -int main(int argc, const char* argv[]) -{ - void* p; - - ASSERT(-1 == (intptr_t)brk((void*)0xffffffff)); - ASSERT(ENOMEM == errno); - - p = sbrk(0); - ASSERT(p == sbrk(0)); - ASSERT(p == sbrk(8)); - ASSERT(p != sbrk(0)); - ASSERT(p != sbrk(-8)); - ASSERT(p == sbrk(0)); - - /* We assume the test environment has less than 2GB of RAM. */ - ASSERT(-1 == (intptr_t)sbrk(INT_MAX)); - ASSERT(-1 == (intptr_t)sbrk(INT_MIN)); - - finished(); -} - diff --git a/plat/qemuppc/tests/build.lua b/plat/qemuppc/tests/build.lua index f0c2993c4..6581d93ef 100644 --- a/plat/qemuppc/tests/build.lua +++ b/plat/qemuppc/tests/build.lua @@ -1,49 +1,7 @@ -include("plat/build.lua") +include("tests/plat/build.lua") -local qemu = "qemu-system-ppc" -local tests = {} - -if os.execute("which "..qemu.." > /dev/null") ~= 0 then - print("warning: skipping tests which require ", qemu) -else - local testcases = filenamesof("./*.c", "./*.s", "./*.e", "./*.p") - - for _, f in ipairs(testcases) do - local fs = replace(basename(f), "%..$", "") - local _, _, lang = fs:find("_(.)$") - if not lang then - lang = "e" - end - - local bin = ackprogram { - name = fs.."_bin", - srcs = { f }, - deps = { "plat/qemuppc/tests/lib+lib" }, - vars = { - plat = "qemuppc", - lang = lang, - ackcflags = "-O0" - } - } - - tests[#tests+1] = normalrule { - name = fs, - outleaves = { "stamp" }, - ins = { - bin, - "./testdriver.sh" - }, - commands = { - "%{ins[2]} "..qemu.." %{ins[1]} 5", - "touch %{outs}" - } - } - end -end - -normalrule { - name = "tests", - outleaves = { "stamp" }, - ins = tests, - commands = { "touch %{outs}" } -} \ No newline at end of file +plat_testsuite { + name = "tests", + plat = "qemuppc", + method = "qemu-system-ppc" +} diff --git a/plat/qemuppc/tests/lib/build.lua b/plat/qemuppc/tests/lib/build.lua deleted file mode 100644 index cb6b5cbea..000000000 --- a/plat/qemuppc/tests/lib/build.lua +++ /dev/null @@ -1,8 +0,0 @@ -include("plat/build.lua") - -acklibrary { - name = "lib", - srcs = { "./test.c" }, - hdrs = { "./test.h" }, - vars = { plat = "qemuppc" } -} diff --git a/plat/qemuppc/tests/testdriver.sh b/plat/qemuppc/tests/testdriver.sh deleted file mode 100755 index 3424e9626..000000000 --- a/plat/qemuppc/tests/testdriver.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh -qemu=$1 -img=$2 -timeout=$3 - -pipe=/tmp/$$.testdriver.pipe -mknod $pipe p -trap "rm -f $pipe" EXIT - -result=/tmp/$$.testdriver.result -trap "rm -f $result" EXIT - -pidfile=/tmp/$$.testdriver.pid -trap "rm -f $pidfile" EXIT - -( $qemu -nographic -kernel $img 2>&1 & echo $! > $pidfile ) \ - | tee $result \ - | ( timeout $timeout grep -l -q @@FINISHED ; echo ) \ - | ( read dummy && kill $(cat $pidfile) ) - -( grep -q @@FAIL $result || ! grep -q @@FINISHED $result ) && cat $result && exit 1 -exit 0 \ No newline at end of file diff --git a/plat/rpi/descr b/plat/rpi/descr index 6daff9606..43d3256a3 100644 --- a/plat/rpi/descr +++ b/plat/rpi/descr @@ -51,17 +51,19 @@ name led mapflag -i SEPID=-b1:0 mapflag -fp FLOATS={EM}/{ILIB}fp args {ALIGN} {SEPID?} \ + ({RTS}:.b=-u _i_main) \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ - ({RTS}:.ocm.b={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.ocm.bas.b={PLATFORMDIR}/c-ansi.o) \ ({RTS}:.c={PLATFORMDIR}/c-ansi.o) \ ({RTS}:.mod={PLATFORMDIR}/modula2.o) \ ({RTS}:.p={PLATFORMDIR}/pascal.o) \ -o > < \ (.p:{TAIL}={PLATFORMDIR}/libpascal.a) \ - (.b:{TAIL}={PLATFORMDIR}/libbasic.a) \ + (.b:{TAIL}={PLATFORMDIR}/libb.a) \ + (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ - (.ocm.b.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + (.ocm.bas.mod.b.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ diff --git a/plat/qemuppc/tests/_dummy.c b/tests/plat/_dummy_e.c similarity index 100% rename from plat/qemuppc/tests/_dummy.c rename to tests/plat/_dummy_e.c diff --git a/tests/plat/b/control_b.b b/tests/plat/b/control_b.b new file mode 100644 index 000000000..a31b9d380 --- /dev/null +++ b/tests/plat/b/control_b.b @@ -0,0 +1,107 @@ +# +zero 0; +one 1; + +if_t() +{ + extrn zero, one; + auto fails, successes; + + successes = 0; + + if (zero) + fail(__LINE__); + + if (zero) + fail(__LINE__); + else + successes++; + + if (one) + successes++; + + if (one) + successes++; + else + fail(__LINE__); + + if (successes != 3) + fail(__LINE__); +} + +while_t() +{ + extrn zero, one; + auto successes, count; + + successes = 3; + count = 0; + while (count) + { + successes++; + count--; + } + if (successes != 3) + fail(__LINE__); + + while (zero) + fail(__LINE__); + + while (one) + { + break; + fail(__LINE__); + } +} + +sdata(n) +{ + switch (n) + { + case 0: return(0); + case 1: return(1); + case 100: return(100); + default: return(-1); + } +} + +switch_t() +{ + extrn zero; + auto successes; + + if (!(sdata(-1) == -1)) fail(__LINE__); + if (!(sdata(0) == 0)) fail(__LINE__); + if (!(sdata(1) == 1)) fail(__LINE__); + if (!(sdata(2) == -1)) fail(__LINE__); + if (!(sdata(100) == 100)) fail(__LINE__); + if (!(sdata(200) == -1)) fail(__LINE__); + + successes = 0; + switch (zero) + { + case 0: /* fall through */ + case 1: successes++; break; + } + if (successes != 1) + fail(__LINE__); +} + +goto_t() +{ + goto n; + fail(__LINE__); + n:; +} + +main() +{ + if_t(); + switch_t(); + goto_t(); + while_t(); + + finished(); + return(0); +} + diff --git a/tests/plat/b/incdec_b.b b/tests/plat/b/incdec_b.b new file mode 100644 index 000000000..4edf5f6bf --- /dev/null +++ b/tests/plat/b/incdec_b.b @@ -0,0 +1,82 @@ +# +/* External variables to defeat constant folding. */ +zero 0; +one 1; + +i 0; + +ext_t() +{ + extrn zero, one, i; + + i = zero; + if (!(i++ == 0)) fail(__LINE__); + + i = one; + if (!(i-- == 1)) fail(__LINE__); + if (!(i == 0)) fail(__LINE__); + + i = zero; + if (!(++i == 1)) fail(__LINE__); + if (!(i == 1)) fail(__LINE__); + + i = one; + if (!(--i == 0)) fail(__LINE__); + if (!(i == 0)) fail(__LINE__); +} + +int_t() +{ + extrn zero, one; + auto i; + + i = zero; + if (!(i++ == 0)) fail(__LINE__); + + i = one; + if (!(i-- == 1)) fail(__LINE__); + if (!(i == 0)) fail(__LINE__); + + i = zero; + if (!(++i == 1)) fail(__LINE__); + if (!(i == 1)) fail(__LINE__); + + i = one; + if (!(--i == 0)) fail(__LINE__); + if (!(i == 0)) fail(__LINE__); +} + +star_t() +{ + extrn zero, one, i; + auto p; + + p = &i; + + i = zero; + if (!((*p)++ == 0)) fail(__LINE__); + + i = one; + if (!((*p)-- == 1)) fail(__LINE__); + if (!(i == 0)) fail(__LINE__); + + i = zero; + if (!(++(*p) == 1)) fail(__LINE__); + if (!(i == 1)) fail(__LINE__); + + i = one; + if (!(--(*p) == 0)) fail(__LINE__); + if (!(i == 0)) fail(__LINE__); +} + +main() +{ + ext_t(); + int_t(); + star_t(); + + finished(); + return(0); +} + + diff --git a/tests/plat/b/operators_b.b b/tests/plat/b/operators_b.b new file mode 100644 index 000000000..5baa674b1 --- /dev/null +++ b/tests/plat/b/operators_b.b @@ -0,0 +1,69 @@ +# +minusone -1; +zero 0; +one 1; +two 2; + +main() +{ + extrn minusone, zero, one, two; + auto i, j; + + if (!(zero == 0)) fail(__LINE__); + if (!(one == 1)) fail(__LINE__); + if (!(-one == -1)) fail(__LINE__); + if (!(!one == 0)) fail(__LINE__); + if (!(!zero == 1)) fail(__LINE__); + if (!(~zero == -1)) fail(__LINE__); + if (!(~minusone == 0)) fail(__LINE__); + + if (!(zero == zero)) fail(__LINE__); + if (!(zero != one)) fail(__LINE__); + if (!(zero < one)) fail(__LINE__); + if (!(zero <= one)) fail(__LINE__); + if (!(zero <= zero)) fail(__LINE__); + if (!(one > zero)) fail(__LINE__); + if (!(one >= zero)) fail(__LINE__); + if (!(one >= one)) fail(__LINE__); + + if (!((two + two) == 4)) fail(__LINE__); + if (!((two - two) == 0)) fail(__LINE__); + if (!((two * two) == 4)) fail(__LINE__); + if (!((two / two) == 1)) fail(__LINE__); + if (!((two % two) == 0)) fail(__LINE__); + + if (!((one << 1) == 2)) fail(__LINE__); + if (!((two >> 1) == 1)) fail(__LINE__); + + if (!((two & 1) == 0)) fail(__LINE__); + if (!((two | 1) == 3)) fail(__LINE__); + if (!((two ^ 2) == 0)) fail(__LINE__); + + i = 2; i =+ two; if (!(i == 4)) fail(__LINE__); + i = 2; i =- two; if (!(i == 0)) fail(__LINE__); + i = 2; i =* two; if (!(i == 4)) fail(__LINE__); + i = 2; i =/ two; if (!(i == 1)) fail(__LINE__); + i = 2; i =% two; if (!(i == 0)) fail(__LINE__); + + i = zero; i === zero; if (!i) fail(__LINE__); + i = zero; i =!= one; if (!i) fail(__LINE__); + i = zero; i =< one; if (!i) fail(__LINE__); + i = zero; i =<= one; if (!i) fail(__LINE__); + i = zero; i =<= zero; if (!i) fail(__LINE__); + i = one; i => zero; if (!i) fail(__LINE__); + i = one; i =>= zero; if (!i) fail(__LINE__); + i = one; i =>= one; if (!i) fail(__LINE__); + + i = one; i =<< one; if (!(i == 2)) fail(__LINE__); + i = two; i =>> one; if (!(i == 1)) fail(__LINE__); + + i = two; i =& 1; if (!(i == 0)) fail(__LINE__); + i = two; i =| 1; if (!(i == 3)) fail(__LINE__); + i = two; i =^ 2; if (!(i == 0)) fail(__LINE__); + + if (!(one ? 1 : 0)) fail(__LINE__); + if (!(zero ? 0 : 1)) fail(__LINE__); + + finished(); + return(0); +} diff --git a/tests/plat/brk_c.c b/tests/plat/brk_c.c new file mode 100644 index 000000000..434cec50b --- /dev/null +++ b/tests/plat/brk_c.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +#include "test.h" + +int main(int argc, const char* argv[]) +{ + char* o; + char* p; + + p = sbrk(0); + ASSERT(p == sbrk(0)); + ASSERT(p == sbrk(8)); + ASSERT(p != sbrk(0)); + ASSERT(p != sbrk(-8)); + ASSERT(p == sbrk(0)); + + errno = 0; + o = sbrk(INT_MAX); + if (o == (char*)-1) + ASSERT(ENOMEM == errno); + else + { + ASSERT(0 == errno); + p = sbrk(0); + ASSERT(p > o); + brk(o); + } + + errno = 0; + o = sbrk(INT_MIN); + if (o == (char*)-1) + ASSERT(ENOMEM == errno); + else + { + ASSERT(0 == errno); + p = sbrk(0); + ASSERT(p < o); + brk(o); + } + + finished(); +} + diff --git a/tests/plat/bugs/bug-22-inn_mod.mod b/tests/plat/bugs/bug-22-inn_mod.mod new file mode 100644 index 000000000..53fe93568 --- /dev/null +++ b/tests/plat/bugs/bug-22-inn_mod.mod @@ -0,0 +1,22 @@ +MODULE test; +FROM Test IMPORT fail, finished; + +TYPE charset = SET OF CHAR; + +PROCEDURE Space(c: CHAR): BOOLEAN; +BEGIN + RETURN c IN charset{' ', 11C, 12C, 15C} +END Space; + +BEGIN + IF Space('a') THEN + fail(1); + END; + IF NOT Space(' ') THEN + fail(2); + END; + IF NOT Space(12C) THEN + fail(3); + END; + finished; +END test. \ No newline at end of file diff --git a/tests/plat/build.lua b/tests/plat/build.lua new file mode 100644 index 000000000..b689ea5f6 --- /dev/null +++ b/tests/plat/build.lua @@ -0,0 +1,70 @@ +include("plat/build.lua") + +definerule("plat_testsuite", + { + plat = { type="string" }, + method = { type="string" }, + }, + function(e) + -- Remember this is executed from the caller's directory; local + -- target names will resolve there. + local testfiles = filenamesof( + "tests/plat/*.c", + "tests/plat/*.e", + "tests/plat/*.p", + "tests/plat/b/*.b", + "tests/plat/bugs/*.mod" + ) + + acklibrary { + name = "lib", + srcs = { + "tests/plat/lib/test.c", + "tests/plat/lib/test_b.c", + }, + hdrs = { + "tests/plat/lib/test.h", + "tests/plat/lib/Test.def" + }, + vars = { plat = e.plat }, + } + + local tests = {} + for _, f in ipairs(testfiles) do + local fs = replace(basename(f), "%.[^.]+$", "") + local _, _, lang = fs:find("_([^_]+)$") + if not lang then + lang = "e" + end + + local bin = ackprogram { + name = fs.."_bin", + srcs = { f }, + deps = { "+lib" }, + vars = { + plat = e.plat, + lang = lang, + ackcflags = "-O0 -Bmain" + } + } + + tests[#tests+1] = normalrule { + name = fs, + outleaves = { e.plat.."-"..fs.."-testlog.txt" }, + ins = { + bin, + "tests/plat/testdriver.sh", + "util/build+testrunner" + }, + commands = { + "(%{ins[2]} "..e.method.." %{ins[1]} 5 %{ins[3]} || echo @@FAIL) > %{outs}", + } + } + end + + return bundle { + name = e.name, + srcs = tests, + } + end +) diff --git a/plat/qemuppc/tests/calloc_c.c b/tests/plat/calloc_c.c similarity index 100% rename from plat/qemuppc/tests/calloc_c.c rename to tests/plat/calloc_c.c diff --git a/plat/qemuppc/tests/csa_e.c b/tests/plat/csa_e.c similarity index 100% rename from plat/qemuppc/tests/csa_e.c rename to tests/plat/csa_e.c diff --git a/plat/qemuppc/tests/csb_e.c b/tests/plat/csb_e.c similarity index 100% rename from plat/qemuppc/tests/csb_e.c rename to tests/plat/csb_e.c diff --git a/plat/qemuppc/tests/doublecmp_e.c b/tests/plat/doublecmp_e.c similarity index 100% rename from plat/qemuppc/tests/doublecmp_e.c rename to tests/plat/doublecmp_e.c diff --git a/plat/qemuppc/tests/from_d_to_si_e.c b/tests/plat/from_d_to_si_e.c similarity index 67% rename from plat/qemuppc/tests/from_d_to_si_e.c rename to tests/plat/from_d_to_si_e.c index 8c7e31c3e..7f51e6c5b 100644 --- a/plat/qemuppc/tests/from_d_to_si_e.c +++ b/tests/plat/from_d_to_si_e.c @@ -1,11 +1,12 @@ +#include #include "test.h" /* Constants in globals to defeat constant folding. */ double one = 1.0; double zero = 0.0; double minusone = -1.0; -double big = 2147483647.0; -double minusbig = -2147483648.0; +double big = (double)INT_MAX; +double minusbig = (double)INT_MIN; /* Bypasses the CRT, so there's no stdio or BSS initialisation. */ void _m_a_i_n(void) @@ -13,8 +14,8 @@ void _m_a_i_n(void) ASSERT((int)zero == 0); ASSERT((int)one == 1); ASSERT((int)minusone == -1); - ASSERT((int)big == 2147483647); - ASSERT((int)minusbig == -2147483648); + ASSERT((int)big == INT_MAX); + ASSERT((int)minusbig == INT_MIN); finished(); } \ No newline at end of file diff --git a/plat/qemuppc/tests/from_d_to_ui_e.c b/tests/plat/from_d_to_ui_e.c similarity index 75% rename from plat/qemuppc/tests/from_d_to_ui_e.c rename to tests/plat/from_d_to_ui_e.c index b16667502..811780b87 100644 --- a/plat/qemuppc/tests/from_d_to_ui_e.c +++ b/tests/plat/from_d_to_ui_e.c @@ -1,16 +1,17 @@ +#include #include "test.h" /* Constants in globals to defeat constant folding. */ double one = 1.0; double zero = 0.0; -double big = 4294967295.0; +double big = (double)UINT_MAX; /* Bypasses the CRT, so there's no stdio or BSS initialisation. */ void _m_a_i_n(void) { ASSERT((unsigned int)zero == 0); ASSERT((unsigned int)one == 1); - ASSERT((unsigned int)big == 4294967295); + ASSERT((unsigned int)big == UINT_MAX); finished(); } \ No newline at end of file diff --git a/plat/qemuppc/tests/from_si_to_d_e.c b/tests/plat/from_si_to_d_e.c similarity index 64% rename from plat/qemuppc/tests/from_si_to_d_e.c rename to tests/plat/from_si_to_d_e.c index e81c2f7c2..b6c7a25ba 100644 --- a/plat/qemuppc/tests/from_si_to_d_e.c +++ b/tests/plat/from_si_to_d_e.c @@ -1,11 +1,12 @@ +#include #include "test.h" /* Constants in globals to defeat constant folding. */ int one = 1; int zero = 0; int minusone = -1; -int big = 0x7fffffff; -int minusbig = -0x8000000; +int big = INT_MAX; +int minusbig = INT_MIN; /* Bypasses the CRT, so there's no stdio or BSS initialisation. */ void _m_a_i_n(void) @@ -13,8 +14,8 @@ void _m_a_i_n(void) ASSERT((double)zero == 0.0); ASSERT((double)one == 1.0); ASSERT((double)minusone == -1.0); - ASSERT((double)big == 2147483647.0); - /* ASSERT((double)minusbig == -2147483648.0); FIXME: fails for now */ + ASSERT((double)big == (double)INT_MAX); + /* ASSERT((double)minusbig == (double)INT_MIN); FIXME: fails for now */ finished(); } \ No newline at end of file diff --git a/plat/qemuppc/tests/from_ui_to_d_e.c b/tests/plat/from_ui_to_d_e.c similarity index 75% rename from plat/qemuppc/tests/from_ui_to_d_e.c rename to tests/plat/from_ui_to_d_e.c index a3517b24c..b8e017c99 100644 --- a/plat/qemuppc/tests/from_ui_to_d_e.c +++ b/tests/plat/from_ui_to_d_e.c @@ -1,16 +1,17 @@ +#include #include "test.h" /* Constants in globals to defeat constant folding. */ unsigned int one_u = 1; unsigned int zero_u = 0; -unsigned int big_u = 0xffffffff; +unsigned int big_u = UINT_MAX; /* Bypasses the CRT, so there's no stdio or BSS initialisation. */ void _m_a_i_n(void) { ASSERT((double)zero_u == 0.0); ASSERT((double)one_u == 1.0); - ASSERT((double)big_u == 4294967295.0); + ASSERT((double)big_u == (double)UINT_MAX); finished(); } \ No newline at end of file diff --git a/plat/qemuppc/tests/inn_e.e b/tests/plat/inn_e.e similarity index 56% rename from plat/qemuppc/tests/inn_e.e rename to tests/plat/inn_e.e index 4e53b35c5..a5aee02f5 100644 --- a/plat/qemuppc/tests/inn_e.e +++ b/tests/plat/inn_e.e @@ -1,5 +1,5 @@ # - mes 2, 4, 4 + mes 2, EM_WSIZE, EM_PSIZE exp $_m_a_i_n pro $_m_a_i_n, 0 @@ -7,7 +7,7 @@ /* Test non-existent bit */ .1 - rom 0I1, 0I1, 0I1, 0I1 + rom 0I4 loe .1 loc 1 /* bit number */ inn 4 @@ -15,59 +15,60 @@ loc __LINE__ cal $fail - ass 4 + ass EM_WSIZE 1 /* Test existent bit */ .2 - rom 2I1, 0I1, 0I1, 0I1 + rom 16384 +.21 + rom 14 /* to defeat constant folding */ + loe .2 - loc 1 /* bit number */ - inn 4 + loe .21 /* bit number */ + inn EM_WSIZE zne *2 loc __LINE__ cal $fail - ass 4 + ass EM_WSIZE 2 /* Test non-existent high bit */ .3 - rom 0I1, 0I1, 0I1, 0I1 - rom 0I1, 0I1, 0I1, 0I1 + rom 0, 0 .31 - rom 33 /* to defeat constant folding */ + rom 8 /* to defeat constant folding */ lae .3 - loi 8 + loi EM_WSIZE*2 loe .31 /* bit number */ - inn 8 + inn EM_WSIZE*2 zeq *3 loc __LINE__ cal $fail - ass 4 + ass EM_WSIZE 3 /* Test existent high bit */ .4 - rom 0I1, 0I1, 0I1, 0I1 - rom 2I1, 0I1, 0I1, 0I1 + rom 0, 2 .41 - rom 33 /* to defeat constant folding */ + rom (EM_WSIZE*8)+1 /* to defeat constant folding */ lae .4 - loi 8 + loi EM_WSIZE*2 loe .41 /* bit number */ - inn 8 + inn EM_WSIZE*2 zne *4 loc __LINE__ cal $fail - ass 4 + ass EM_WSIZE 4 cal $finished diff --git a/plat/qemuppc/tests/intadd_e.c b/tests/plat/intadd_e.c similarity index 100% rename from plat/qemuppc/tests/intadd_e.c rename to tests/plat/intadd_e.c diff --git a/plat/qemuppc/tests/intcmp_e.c b/tests/plat/intcmp_e.c similarity index 100% rename from plat/qemuppc/tests/intcmp_e.c rename to tests/plat/intcmp_e.c diff --git a/plat/qemuppc/tests/intdiv_e.c b/tests/plat/intdiv_e.c similarity index 100% rename from plat/qemuppc/tests/intdiv_e.c rename to tests/plat/intdiv_e.c diff --git a/plat/qemuppc/tests/intrem_e.c b/tests/plat/intrem_e.c similarity index 100% rename from plat/qemuppc/tests/intrem_e.c rename to tests/plat/intrem_e.c diff --git a/plat/qemuppc/tests/intshift_e.c b/tests/plat/intshift_e.c similarity index 83% rename from plat/qemuppc/tests/intshift_e.c rename to tests/plat/intshift_e.c index dd280142c..3cc6d52f9 100644 --- a/plat/qemuppc/tests/intshift_e.c +++ b/tests/plat/intshift_e.c @@ -1,3 +1,4 @@ +#include #include "test.h" /* Constants in globals to defeat constant folding. */ @@ -25,8 +26,8 @@ void _m_a_i_n(void) ASSERT(((unsigned int)one >>(unsigned int)zero) == 1); ASSERT(((unsigned int)one >>(unsigned int)one) == 0); - ASSERT(((unsigned int)minusone>>(unsigned int)zero) == 0xffffffff); - ASSERT(((unsigned int)minusone>>(unsigned int)one) == 0x7fffffff); + ASSERT(((unsigned int)minusone>>(unsigned int)zero) == UINT_MAX); + ASSERT(((unsigned int)minusone>>(unsigned int)one) == (UINT_MAX>>1)); ASSERT((one <<0) == 1); ASSERT((one <<1) == 2); @@ -45,8 +46,8 @@ void _m_a_i_n(void) ASSERT(((unsigned int)one >>(unsigned int)0) == 1); ASSERT(((unsigned int)one >>(unsigned int)1) == 0); - ASSERT(((unsigned int)minusone>>(unsigned int)0) == 0xffffffff); - ASSERT(((unsigned int)minusone>>(unsigned int)1) == 0x7fffffff); + ASSERT(((unsigned int)minusone>>(unsigned int)0) == UINT_MAX); + ASSERT(((unsigned int)minusone>>(unsigned int)1) == (UINT_MAX>>1)); finished(); } \ No newline at end of file diff --git a/plat/qemuppc/tests/intsub_e.c b/tests/plat/intsub_e.c similarity index 73% rename from plat/qemuppc/tests/intsub_e.c rename to tests/plat/intsub_e.c index 72ba0ff08..d8f67d3a3 100644 --- a/plat/qemuppc/tests/intsub_e.c +++ b/tests/plat/intsub_e.c @@ -1,3 +1,4 @@ +#include #include "test.h" /* Constants in globals to defeat constant folding. */ @@ -19,13 +20,13 @@ void _m_a_i_n(void) ASSERT((1 - two) == -1); ASSERT(((unsigned int)two - (unsigned int)one) == 1); - ASSERT(((unsigned int)one - (unsigned int)two) == 0xffffffff); + ASSERT(((unsigned int)one - (unsigned int)two) == UINT_MAX); ASSERT(((unsigned int)two - (unsigned int)1) == 1); - ASSERT(((unsigned int)one - (unsigned int)2) == 0xffffffff); + ASSERT(((unsigned int)one - (unsigned int)2) == UINT_MAX); ASSERT(((unsigned int)2 - (unsigned int)one) == 1); - ASSERT(((unsigned int)1 - (unsigned int)two) == 0xffffffff); + ASSERT(((unsigned int)1 - (unsigned int)two) == UINT_MAX); finished(); } \ No newline at end of file diff --git a/tests/plat/lib/Test.def b/tests/plat/lib/Test.def new file mode 100644 index 000000000..cab31f2e8 --- /dev/null +++ b/tests/plat/lib/Test.def @@ -0,0 +1,6 @@ +(*$Foreign*) +DEFINITION MODULE Test; + PROCEDURE finished(); + PROCEDURE writehex(code: LONGINT); + PROCEDURE fail(code: LONGINT); +END Test. diff --git a/plat/qemuppc/tests/lib/test.c b/tests/plat/lib/test.c similarity index 71% rename from plat/qemuppc/tests/lib/test.c rename to tests/plat/lib/test.c index 33d72f3ce..426f9944a 100644 --- a/plat/qemuppc/tests/lib/test.c +++ b/tests/plat/lib/test.c @@ -6,6 +6,7 @@ void finished(void) { static const char s[] = "@@FINISHED\n"; write(1, s, sizeof(s)); + _exit(0); } void writehex(uint32_t code) @@ -25,7 +26,10 @@ void writehex(uint32_t code) void fail(uint32_t code) { - write(1, "@@FAIL on line 0x", 7); + static const char fail_msg[] = "@@FAIL 0x"; + static const char nl_msg[] = "\n"; + + write(1, fail_msg, sizeof(fail_msg)-1); writehex(code); - write(1, "\n", 1); + write(1, nl_msg, sizeof(nl_msg)-1); } diff --git a/plat/qemuppc/tests/lib/test.h b/tests/plat/lib/test.h similarity index 79% rename from plat/qemuppc/tests/lib/test.h rename to tests/plat/lib/test.h index 96537a2cb..db16506f9 100644 --- a/plat/qemuppc/tests/lib/test.h +++ b/tests/plat/lib/test.h @@ -9,6 +9,6 @@ extern void writehex(uint32_t code); extern void fail(uint32_t code); #define ASSERT(condition) \ - if (!(condition)) fail(__LINE__) + do { if (!(condition)) fail(__LINE__); } while(0) #endif diff --git a/tests/plat/lib/test_b.c b/tests/plat/lib/test_b.c new file mode 100644 index 000000000..b2173b4f3 --- /dev/null +++ b/tests/plat/lib/test_b.c @@ -0,0 +1,34 @@ +#include +#include "test.h" + +extern void patch_addresses(uintptr_t* module); +extern uintptr_t* bmodule_main; + +static void i_writehex(intptr_t code) +{ + writehex(code); +} + +static void i_fail(intptr_t code) +{ + fail(code); +} + +uintptr_t b_finished = (uintptr_t)&finished; +uintptr_t b_writehex = (uintptr_t)&i_writehex; +uintptr_t b_fail = (uintptr_t)&i_fail; + +static uintptr_t* bmodule_test[] = +{ + &b_finished, + &b_writehex, + &b_fail, + 0 +}; + +void binit(void) +{ + patch_addresses(&bmodule_test); + patch_addresses(&bmodule_main); +} + diff --git a/plat/qemuppc/tests/newdispose_p.p b/tests/plat/newdispose_p.p similarity index 98% rename from plat/qemuppc/tests/newdispose_p.p rename to tests/plat/newdispose_p.p index 36f09e99b..aa3be5a46 100644 --- a/plat/qemuppc/tests/newdispose_p.p +++ b/tests/plat/newdispose_p.p @@ -9,13 +9,13 @@ type var ptr1 : iptr; ptr2 : iptr; - + procedure finished; extern; procedure fail(line: integer); extern; - + #define ASSERT(cond) \ if (not (cond)) then fail(__LINE__) diff --git a/tests/plat/pascalsets_p.p b/tests/plat/pascalsets_p.p new file mode 100644 index 000000000..b443b492d --- /dev/null +++ b/tests/plat/pascalsets_p.p @@ -0,0 +1,37 @@ +# +(*$U+ -- enables underscores in identifiers *) + +program pascalsets; + +type + charset = set of char; + +var + s : charset; + i : integer; + +procedure finished; + extern; + +procedure fail(line: integer); + extern; + +#define ASSERT(cond) \ + if (not (cond)) then fail(__LINE__) + +begin + s := []; + for i := 0 to 255 do + s := s + [chr(i)]; + + i := 99; (* to defeat optimisation *) + ASSERT(chr(42) in s); + ASSERT(chr(142) in s); + ASSERT(chr(i) in s); + s := s - [chr(42)]; + ASSERT(not(chr(42) in s)); + ASSERT(chr(142) in s); + ASSERT(chr(i) in s); + + finished +end. diff --git a/tests/plat/testdriver.sh b/tests/plat/testdriver.sh new file mode 100755 index 000000000..384c83b47 --- /dev/null +++ b/tests/plat/testdriver.sh @@ -0,0 +1,52 @@ +#!/bin/sh +method=$1 +img=$2 +timeout=$3 +timeoutprog=$4 + +set -e + +result=/tmp/$$.testdriver.result +trap "rm -f $result" EXIT + +errcho() { + >&2 echo "$*" +} + +get_test_output() { + case $method in + qemu-system-*) + if ! command -v $method >/dev/null 2>&1 ; then + errcho "Warning: $method not installed, skipping test" + echo "@@SKIPPED" + exit 0 + fi + + case $method in + qemu-system-i386) img="-drive file=$img,if=floppy,format=raw" ;; + qemu-system-ppc) img="-kernel $img" ;; + esac + + $timeoutprog -t $timeout -- $method -nographic $img > $result 2>&1 + ;; + + qemu-*) + if ! command -v $method >/dev/null 2>&1 ; then + errcho "Warning: $method not installed, skipping test" + echo "@@SKIPPED" + exit 0 + fi + + $method $img > $result 2>&1 + ;; + + *) + errcho "Error: $method not known by testdriver" + exit 1 + ;; + esac +} + +get_test_output +( grep -q '@@FAIL\|@@SKIPPED' $result || ! grep -q @@FINISHED $result ) && cat $result && exit 1 +exit 0 diff --git a/util/ack/ack.1.X b/util/ack/ack.1.X index 689992ac7..8ea920586 100644 --- a/util/ack/ack.1.X +++ b/util/ack/ack.1.X @@ -1,20 +1,12 @@ -.\" $Id$ -.de SB -.\" SuBheader -.sp 1 -.PP -.nr Sf \\n(.f -.ft B -\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9 -.ft \\n(Sf -.sp 1 -.. -.TH ACK 1 "$Revision$" +.TH ACK 1 2017-01-18 .ad +. .SH NAME ack \- Amsterdam Compiler Kit +. .SH SYNOPSIS \fBack\fP arguments +. .SH DESCRIPTION This program transforms sources in several languages to load files for a variety of machines, @@ -51,6 +43,8 @@ Pascal program. .IP .c C module. .IP .b +B module. +.IP .bas Basic program. .IP .ocm Occam program. @@ -68,10 +62,8 @@ Optimized compact EM assembly code. Machine assembly language code. .IP .o Object file. -.PP - +. .SH OPTIONS - \fIAck\fP accepts the following flags: .IP \-m\fImachine\fP This flag tells \fIack\fP to generate a load file for \fImachine\fP. @@ -100,8 +92,9 @@ Note: \fIack\fP refuses to overwrite argument \fI.e\fP files. .IP \-t Preserve all intermediate files. If two \fB\-t\fP are used, -\fIack\fP also preserves core dumps and output of failed transformations. - +\fIack\fP also preserves output of failed transformations. +. +.sp 1 .IP \-w Suppress all warning messages. .IP \-v @@ -113,7 +106,8 @@ Tell the C-compiler to conform to "Kernighan & Ritchie" C. Tell \fIack\fP to use the ANSI C compiler instead of the old one. .IP \-fp Use the software floating point package, if present. - +. +.sp 1 .IP \-I\fIdir\fP \&\`#include\' files whose names do not begin with \`/\' are always sought first in the directory of the \fIfile\fP argument, @@ -131,7 +125,8 @@ preprocessing. Don't generate line directives. .IP \-C Leave C-comments in. - +. +.sp 1 .IP \-p This flag tells both the Pascal and C front ends to include code enabling the user to do some monitoring/debugging. @@ -139,7 +134,16 @@ Each time a routine is entered the routine \fBprocentry\fP is called and just before each return \fBprocexit\fP is called. These routines are supplied with one parameter, a pointer to a string containing the name of the routine. - +. +.sp 1 +.IP \-B\fIname\fP +Tells the B front end what the name of the module being compiled is, for use +with separate compilation. +Defaults to +.I main +if not specified. See the section below on compiling B. +. +.sp 1 .IP \-O .IP \-O\fInum\fP .IP \-O\fIopt1,opt2,...\fP @@ -228,7 +232,8 @@ for higher levels: as for \-O4. Disable the generation of code by the front ends to record line number and source file name at run-time. (This is the default for C and Fortran). - +. +.sp 1 .IP \-l\fIname\fP Tells \fIack\fP to insert a library module at this point. For example: the library \fImon\fP contains the @@ -248,13 +253,14 @@ These flags tell \fIack\fP to include the libraries needed when a file with \fIsuffix\fP would be included in the arguments. .IP \-LIB This flag tells the peephole optimizer -.RF em_opt 6 +em_opt(6) to add information about the visibility of the names used to each output module. This is needed by assembler/linkers when these modules are to be inserted in libraries. - +. +.sp 1 .IP \-{xxx} The string starting after \`{\' and terminated by a \`}\' is passed as an option string to the Pascal compiler and supersedes corresponding @@ -282,7 +288,8 @@ the defaults per program. The changed options are recorded in the "e.out" header. These flags \-\- and \-+ are passed to the assembler for this purpose. So, \-\-t and \-+pfce invert the defaults. - +. +.sp 1 .IP \-R\fIprogram=xxx\fP Replace the \fIprogram\fP by the pathname \fIxxx\fP. The program names referred to later in this manual are allowed here. @@ -309,6 +316,7 @@ Sparc, Vax, Intel 80386. .PP All arguments without a suffix or with an unrecognized suffix are passed to the loaders, as for flags. +. .SH PREPROCESSOR All C source programs are run through the preprocessor before they are fed to the compiler proper. @@ -329,13 +337,47 @@ EM_WSIZE:wordsize:EM_PSIZE:pointer size EM_SSIZE:size of shorts (C):EM_LSIZE:size of longs (C+Pascal) EM_FSIZE:size of floats (C):EM_DSIZE:size of doubles (C+Pascal) .TE -.sp 1 +.PP The name of the \fImachine\fP or something like it when the machine name is numeric is also defined (as 1). As the ANSI C rules forbid this, in ANSI C, underscores are prepended to these names. .PP The default directories searched for include files differ for each machine. +. +.SH COMPILING B +B programs have special needs when compiled with the ACK. +B modules have to be +initialised before use, to convert pointer addresses to word addresses; this is +done automatically when compiling a single B source file to an executable, but +must be done manually when using separate compilation. +.PP +To do this, compile your B modules with the \fI-B\fP option as usual, and then +use the +.B abmodules +program to scan the object files and emit a C file which performs the +initialisation. +Then compile this as well into an object file, and link the +whole lot together. +The result will be a runnable executable. +.PP +Beware \(em referring to an uninitialised module will cause your program to +crash! +.PP +The default initialiser in the B standard library looks for a module called +\fBmain\fP. +.PP +For example: +.nf +.sp +ack -c -mpc86 thismodule.b -Bthismodule +ack -c -mpc86 thatmodule.b -Bthatmodule +ack -c -mpc86 theothermodule.b -Btheothermodule +abmodules -o binit.c thismodule.o thatmodule.o theothermodule.o +ack -c -mpc86 binit.c +ack -mpc86 -o pc86.exe thismodule.o thatmodule.o theothermodule.o binit.o +.fi +. .SH PROGRAMS \fIAck\fP uses one or more programs in each phase of the transformation. @@ -354,7 +396,7 @@ input:name:output:description \&.f:f77:.c:Fortran-to-C front end \&.c:cem:.k:C front end [4,5,6] \&.p:pc:.k:Pascal front end [2,3,6] -\&.b:abc:.k:Basic front end [6,8] +\&.b:basic:.k:Basic front end [6,8] \&.ocm:ocm:.k:Occam front end [9] \&.mod:m2:.k:Modula-2 front end [11] \&.e:encode:.k:Compactify EM assembly language [1] @@ -372,6 +414,7 @@ input:name:output:description \&.o:cv:a.out:Conversion from Ack object to machine object .TE .in -2 +. .SH "ENVIRONMENT VARIABLES" .IP ACKDIR If set, this environment variable overrides ack's idea of its home @@ -382,13 +425,14 @@ machine it compiles for. .IP ACKFE If set, this environment variable tells ack where to get the front-end description file. +. .SH "SEE ALSO" -.PD 0 em_opt(6), em_ass(6), em_cg(6), ack.out(5) .IP [1] A.S. Tanenbaum, Hans van Staveren, Ed Keizer and Johan Stevenson, \fIDescription of a machine architecture for use with block structured languages\fP, Informatica rapport IR-81. +.PD 0 .IP [2] K. Jensen and N. Wirth, \fIPASCAL, User manual and report\fP Springer Verlag. @@ -413,12 +457,13 @@ Informatica rapport IR-99. .IP [11] C.J.H. Jacobs, \fIThe ACK Modula-2 Compiler\fP. .PD +. .SH DIAGNOSTICS -.PD The diagnostics are intended to be self\-explanatory. +. .SH BUGS Not all warning messages are superseded by \fB\-w\fP. -.br +.PP Argument assembly files are not preprocessed when fed into the universal assembler/loader. .SH AUTHOR diff --git a/util/ack/ack.h b/util/ack/ack.h index 0877a8c0d..01eec8212 100644 --- a/util/ack/ack.h +++ b/util/ack/ack.h @@ -6,6 +6,8 @@ #define RCS_ACK "$Id$" #endif +#include /* size_t, free() */ + /****************************************************************************/ /* User settable options */ /****************************************************************************/ @@ -61,20 +63,29 @@ typedef struct { #define p_cont(elem) ((path *)l_content(elem)) -/* Return values of setpath() */ -enum f_path { F_OK, F_NOMATCH, F_NOPATH } ; - /* Own routines */ -enum f_path getpath(); -enum f_path scan_end(); -extern void noodstop(); -extern char *getvar(); -extern char *keeps(); -extern char *basename(); -extern char *skipblank(); -extern char *firstblank(); -extern char *getcore(); -extern char *changecore(); + +/* rmach.c */ +void setlist(char *); + +/* svars.c */ +void setsvar(char *, char *); +void setpvar(char *, char *(*)(void)); +char *getvar(const char *); + +/* util.c */ +char *ack_basename(const char *); +char *skipblank(char *); +char *firstblank(char *); +void fatal(const char *, ...); +void vprint(const char *, ...); +void fuerror(const char *, ...); +void werror(const char *, ...); +void quit(int); +char *keeps(const char *); +#define throws(str) free(str) +void *getcore(size_t); +void *changecore(void *, size_t); #define freecore(area) free(area) #define DEBUG 1 /* Allow debugging of Ack */ diff --git a/util/ack/build.lua b/util/ack/build.lua index 4394484b4..cb9b66fd4 100644 --- a/util/ack/build.lua +++ b/util/ack/build.lua @@ -18,12 +18,28 @@ normalrule { cprogram { name = "ack", srcs = { - "./*.c", + "./data.c", + "./files.c", + "./grows.c", + "./list.c", + "./main.c", + "./rmach.c", + "./run.c", + "./scan.c", + "./svars.c", + "./trans.c", + "./util.c", "+tables", }, deps = { "h+emheaders", "h+local", + "./ack.h", + "./data.h", + "./dmach.h", + "./grows.h", + "./list.h", + "./trans.h", } } diff --git a/util/ack/data.h b/util/ack/data.h index d6ae07855..ea845c4f7 100644 --- a/util/ack/data.h +++ b/util/ack/data.h @@ -48,4 +48,4 @@ EXTERN path in; /* The current single input pathname */ EXTERN path out; /* The current output pathname */ EXTERN path orig; /* The original input path */ EXTERN char *p_basename; /* The current basename */ -EXTERN char *p_suffix; /* The current input suffix */ +EXTERN const char *p_suffix; /* The current input suffix */ diff --git a/util/ack/files.c b/util/ack/files.c index f2dbc8ed2..e149b90f7 100644 --- a/util/ack/files.c +++ b/util/ack/files.c @@ -16,7 +16,7 @@ static char rcs_id[] = "$Id$" ; #endif -char *add_u(part,ptr) char *ptr ; { +static char *add_u(int part, char *ptr) { if ( part>=26 ) { ptr=add_u(part/26-1,ptr) ; } @@ -24,7 +24,7 @@ char *add_u(part,ptr) char *ptr ; { return ptr+1 ; } -char *unique() { +static char *unique(void) { /* Get the next unique part of the internal filename */ static int u_next = 0 ; static char buf[10] ; @@ -36,7 +36,7 @@ char *unique() { return buf ; } -setfiles(phase) register trf *phase ; { +int setfiles(trf *phase) { /* Set the out structure according to the in structure, the transformation and some global data */ growstring pathname ; @@ -94,18 +94,7 @@ setfiles(phase) register trf *phase ; { return 1 ; } -disc_files(phase) trf *phase ; { - path temp ; - - if ( !phase->t_combine ) { - file_final(&in) ; - } else { - disc_inputs(phase) ; - } - temp=in ; in=out ; out=temp ; -} - -file_final(file) path *file ; { +static void file_final(path *file) { if ( file->p_path ) { if ( !file->p_keep && t_flag<=1 ) { if ( unlink(file->p_path)!=0 ) { @@ -119,7 +108,18 @@ file_final(file) path *file ; { file->p_keep=NO ; } -disc_inputs(phase) trf *phase ; { +void disc_files(trf *phase) { + path temp ; + + if ( !phase->t_combine ) { + file_final(&in) ; + } else { + disc_inputs(phase) ; + } + temp=in ; in=out ; out=temp ; +} + +void disc_inputs(trf *phase) { /* Remove all the input files of this phase */ /* Only for combiners */ register path *l_in ; @@ -132,7 +132,7 @@ disc_inputs(phase) trf *phase ; { l_clear(&phase->t_inputs) ; } -rmfile(file) path *file ; { +void rmfile(path *file) { /* Remove a file, do not complain when is does not exist */ if ( file->p_path ) { if ( t_flag<=1 ) unlink(file->p_path) ; @@ -143,8 +143,7 @@ rmfile(file) path *file ; { } } -void -rmtemps() { +void rmtemps(void) { /* Called in case of disaster, always remove the current output file! */ register list_elem *elem ; @@ -159,7 +158,7 @@ rmtemps() { } } -add_input(file,phase) path *file ; trf *phase ; { +void add_input(path *file, trf *phase) { register path *store ; #ifdef DEBUG if ( debug ) { diff --git a/util/ack/grows.c b/util/ack/grows.c index 81c3c002d..a74e27731 100644 --- a/util/ack/grows.c +++ b/util/ack/grows.c @@ -19,7 +19,7 @@ static char rcs_id[] = "$Id$" ; static char rcs_grows[] = RCS_GROWS ; #endif -gr_add(id,c) register growstring *id ; char c ; { +int gr_add(growstring *id, int c) { if ( id->gr_size==id->gr_max) { if ( id->gr_size==0 ) { /* The first time */ id->gr_max= 2*GR_MORE ; @@ -32,8 +32,8 @@ gr_add(id,c) register growstring *id ; char c ; { *(id->gr_string+id->gr_size++)= c ; } -gr_cat(id,string) growstring *id ; char *string ; { - register char *ptr ; +int gr_cat(growstring *id, const char *string) { + const char *ptr ; #ifdef DEBUG if ( id->gr_size && *(id->gr_string+id->gr_size-1) ) { @@ -50,8 +50,7 @@ gr_cat(id,string) growstring *id ; char *string ; { } } -void -gr_throw(id) register growstring *id ; { +void gr_throw(growstring *id) { /* Throw the string away */ if ( id->gr_max==0 ) return ; freecore(id->gr_string) ; @@ -60,11 +59,11 @@ gr_throw(id) register growstring *id ; { id->gr_size=0 ; } -gr_init(id) growstring *id ; { +void gr_init(growstring *id) { id->gr_size=0 ; id->gr_max=0 ; } -char *gr_final(id) growstring *id ; { +char *gr_final(growstring *id) { /* Throw away the bookkeeping, adjust the string to its final length and return a pointer to a string to be get rid of with throws diff --git a/util/ack/grows.h b/util/ack/grows.h index 9b9511049..04f95aa59 100644 --- a/util/ack/grows.h +++ b/util/ack/grows.h @@ -20,8 +20,8 @@ typedef struct { /* Routines used */ -extern void gr_throw() ; /* To free the core */ -extern int gr_add() ; /* To add one character */ -extern int gr_cat() ; /* concatenate the contents and the string */ -extern int gr_init() ; /* Initialize the bookkeeping */ -extern char *gr_final() ; /* Transform to a stable storage string */ +void gr_throw(growstring *) ; /* To free the core */ +int gr_add(growstring *, int) ; /* To add one character */ +int gr_cat(growstring *, const char *) ; /* To append a string */ +void gr_init(growstring *) ; /* Initialize the bookkeeping */ +char *gr_final(growstring *) ; /* Move to a stable storage string */ diff --git a/util/ack/list.c b/util/ack/list.c index 278f55580..5370e96cb 100644 --- a/util/ack/list.c +++ b/util/ack/list.c @@ -33,7 +33,7 @@ Routines: */ -l_add(header,string) list_head *header ; char *string ; { +void l_add(list_head *header, char *string) { register list_elem *new; /* NOSTRICT */ @@ -49,7 +49,7 @@ l_add(header,string) list_head *header ; char *string ; { header->ca_last= new ; } -l_clear(header) list_head *header ; { +void l_clear(list_head *header) { register list_elem *old, *next; for ( old=header->ca_first ; old ; old= next ) { next= old->ca_next ; @@ -59,7 +59,7 @@ l_clear(header) list_head *header ; { header->ca_last = (list_elem *) 0 ; } -l_throw(header) list_head *header ; { +void l_throw(list_head *header) { register list_elem *old, *next; for ( old=header->ca_first ; old ; old= next ) { throws(l_content(*old)) ; diff --git a/util/ack/list.h b/util/ack/list.h index 3e6d55170..f96d8ce15 100644 --- a/util/ack/list.h +++ b/util/ack/list.h @@ -29,3 +29,7 @@ typedef struct ca_elem list_elem ; /* The decl. for elements */ /* To be used for scanning lists, ptr is the running variable */ #define scanlist(elem,ptr) \ for ( ptr= elem ; ptr; ptr= l_next(*ptr) ) + +void l_add(list_head *, char *); +void l_clear(list_head *); +void l_throw(list_head *); diff --git a/util/ack/main.c b/util/ack/main.c index 99e27dceb..a57454d60 100644 --- a/util/ack/main.c +++ b/util/ack/main.c @@ -15,444 +15,569 @@ #include #ifndef NORCSID -static char rcs_id[] = "$Id$" ; -static char rcs_ack[] = RCS_ACK ; +static char rcs_id[] = "$Id$"; +static char rcs_ack[] = RCS_ACK; #endif -static int sigs[] = { SIGINT, SIGHUP, SIGTERM, 0 } ; +static int sigs[] = { SIGINT, SIGHUP, SIGTERM, 0 }; static int arg_count; -extern char *getenv(); +static char* srcvar(void); +static char* getsuffix(void); +static void varinit(void); +static void vieuwargs(int, char**); +static void firstarg(char*); +static int process(char*); +static int startrf(trf*); +static void block(trf*); +static int mayprep(void); +static void scanneeds(void); +static void setneeds(const char*, int); +static void noodstop(int); -void vieuwargs(); +int main(int argc, char** argv) +{ + register list_elem* elem; + register char* frontend; + register int* n_sig; + register trf* phase; -main(argc,argv) char **argv ; { - register list_elem *elem ; - register char *frontend ; - register int *n_sig ; - register trf *phase ; - - progname=argv[0]; + progname = argv[0]; varinit(); - vieuwargs(argc,argv); - if ( (frontend=getenv("ACKFE")) ) { - setlist(frontend) ; - } else { + vieuwargs(argc, argv); + if ((frontend = getenv("ACKFE"))) + { + setlist(frontend); + } + else + { setlist(FRONTENDS); } - if ( callname ) { - if ( machine ) { + if (callname) + { + if (machine) + { fuerror("can not produce code for both %s and %s", - callname,machine) ; + callname, machine); } - machine= callname ; + machine = callname; } - if ( !machine && ! (machine=getenv("ACKM")) ) { + if (!machine && !(machine = getenv("ACKM"))) + { #ifdef ACKM - machine= ACKM; /* The default machine */ + machine = ACKM; /* The default machine */ #else - fuerror("No machine specified") ; + fuerror("No machine specified"); #endif } setlist(machine); /* Find the linker, needed for argument building */ - scanlist(l_first(tr_list),elem) { - if ( t_cont(*elem)->t_linker ) { - linker= t_cont(*elem) ; + scanlist(l_first(tr_list), elem) + { + if (t_cont(*elem)->t_linker) + { + linker = t_cont(*elem); } } transini(); scanneeds(); - sprintf(template,TMPNAME,getpid()) ; - if ( n_error && !k_flag ) exit(n_error) ; + sprintf(template, TMPNAME, getpid()); + if (n_error && !k_flag) + exit(n_error); - for ( n_sig=sigs ; *n_sig ; n_sig++ ) { - if ( signal(*n_sig,noodstop)==SIG_IGN ) { - signal(*n_sig,SIG_IGN) ; + for (n_sig = sigs; *n_sig; n_sig++) + { + if (signal(*n_sig, noodstop) == SIG_IGN) + { + signal(*n_sig, SIG_IGN); } } - scanlist ( l_first(arguments), elem ) { + scanlist(l_first(arguments), elem) + { arg_count++; } - scanlist ( l_first(arguments), elem ) { - if ( !process(l_content(*elem)) && !k_flag ) exit(1) ; + scanlist(l_first(arguments), elem) + { + if (!process(l_content(*elem)) && !k_flag) + exit(1); } - orig.p_path= (char *)0 ; - if ( !rts ) rts="." ; - setsvar(keeps(RTS),rts) ; - if ( linker ) getmapflags(linker) ; + orig.p_path = (char*)0; + if (!rts) + rts = "."; + setsvar(keeps(RTS), rts); + if (linker) + getmapflags(linker); - scanlist(l_first(tr_list),elem) { - phase=t_cont(*elem) ; - if ( phase->t_combine && phase->t_do ) { - if ( phase->t_blocked ) { + scanlist(l_first(tr_list), elem) + { + phase = t_cont(*elem); + if (phase->t_combine && phase->t_do) + { + if (phase->t_blocked) + { #ifdef DEBUG - if ( debug ) { + if (debug) + { vprint("phase %s is blocked\n", - phase->t_name) ; + phase->t_name); } #endif - disc_inputs(phase) ; - continue ; + disc_inputs(phase); + continue; } - orig.p_keep=YES ; - orig.p_keeps=NO ; - orig.p_path=phase->t_origname ; - if ( p_basename ) throws(p_basename) ; - if ( orig.p_path ) { - p_basename= keeps(basename(orig.p_path)) ; - } else { - p_basename=0 ; + orig.p_keep = YES; + orig.p_keeps = NO; + orig.p_path = phase->t_origname; + if (p_basename) + throws(p_basename); + if (orig.p_path) + { + p_basename = keeps(ack_basename(orig.p_path)); } - if ( !startrf(phase) && !k_flag ) exit(1) ; + else + { + p_basename = 0; + } + if (!startrf(phase) && !k_flag) + exit(1); } } - if ( n_error ) exit(n_error) ; + if (n_error) + exit(n_error); - exit(0) ; + exit(0); } -char *srcvar() { - return orig.p_path ; +static char* srcvar(void) +{ + return orig.p_path; } -char *getsuffix() { - return strrchr(orig.p_path, SUFCHAR) ; +static char* getsuffix(void) +{ + return strrchr(orig.p_path, SUFCHAR); } -varinit() { +static void varinit(void) +{ /* initialize the string variables */ - register char *envstr ; - extern char *em_dir; + register char* envstr; + extern char* em_dir; - if ( envstr=getenv("ACKDIR") ) { + if (envstr = getenv("ACKDIR")) + { em_dir = keeps(envstr); } - setsvar(keeps(HOME),em_dir) ; - setpvar(keeps(SRC),srcvar) ; - setpvar(keeps(SUFFIX),getsuffix) ; + setsvar(keeps(HOME), em_dir); + setpvar(keeps(SRC), srcvar); + setpvar(keeps(SUFFIX), getsuffix); } /************************* flag processing ***********************/ -void -vieuwargs(argc,argv) char **argv ; { - register char *argp; - register int nextarg ; - register int eaten ; - int hide ; +void vieuwargs(int argc, char** argv) +{ + register char* argp; + register int nextarg; + register int eaten; + int hide; - firstarg(argv[0]) ; + firstarg(argv[0]); - nextarg= 1 ; + nextarg = 1; - while ( nextarg=argc ) { - fuerror("-o can't be the last flag") ; - } - if ( outfile ) fuerror("Two results?") ; - outfile= argv[nextarg++] ; - hide=YES ; - break ; - case 'O': Optlevel = atoi(&argp[2]); - if (! Optlevel) Optlevel = 1; - Optlist= &argp[2] ; - eaten=1 ; - break ; - case 'v': if ( argp[2] ) { - v_flag += atoi(&argp[2]) ; - eaten=1 ; - } else { - v_flag++ ; - } + hide = NO; /* Do not hide this flags to the phases */ + eaten = 0; /* Did not 'eat' tail of flag yet */ + switch (argp[1]) + { + case 'm': + if (machine) + fuerror("Two machines?"); + machine = &argp[2]; + if (*machine == '\0') + { + fuerror("-m needs machine name"); + } + eaten = 1; + break; + case 'o': + if (nextarg >= argc) + { + fuerror("-o can't be the last flag"); + } + if (outfile) + fuerror("Two results?"); + outfile = argv[nextarg++]; + hide = YES; + break; + case 'O': + Optlevel = atoi(&argp[2]); + if (!Optlevel) + Optlevel = 1; + Optlist = &argp[2]; + eaten = 1; + break; + case 'v': + if (argp[2]) + { + v_flag += atoi(&argp[2]); + eaten = 1; + } + else + { + v_flag++; + } #ifdef DEBUG - if ( v_flag>=3 ) debug=v_flag-2 ; + if (v_flag >= 3) + debug = v_flag - 2; #endif - break ; - case 'c': if ( stopsuffix ) fuerror("Two -c flags") ; - stopsuffix= &argp[2]; eaten=1; - if ( *stopsuffix && *stopsuffix!=SUFCHAR ) { - fuerror("-c flag has invalid tail") ; - } - break ; - case 'k': k_flag++ ; - break ; - case 't': t_flag++ ; - break ; - case 'R': eaten=1; - break ; - case 'r': if ( argp[2]!=SUFCHAR ) { - error("-r must be followed by %c",SUFCHAR) ; - } - keeptail(&argp[2]); eaten=1 ; - break ; - case '.': if ( rts ) { - if ( strcmp(rts,&argp[1])!=0 ) - fuerror("Two run-time systems?") ; - } else { - rts= &argp[1] ; - keephead(rts) ; keeptail(rts) ; - } - eaten=1 ; - break ; - case 0 : nill_flag++ ; eaten++ ; - hide=YES ; - break; - case 'w': w_flag++; - break ; - default: /* The flag is not recognized, + break; + case 'c': + if (stopsuffix) + fuerror("Two -c flags"); + stopsuffix = &argp[2]; + eaten = 1; + if (*stopsuffix && *stopsuffix != SUFCHAR) + { + fuerror("-c flag has invalid tail"); + } + break; + case 'k': + k_flag++; + break; + case 't': + t_flag++; + break; + case 'R': + eaten = 1; + break; + case 'r': + if (argp[2] != SUFCHAR) + { + error("-r must be followed by %c", SUFCHAR); + } + l_add(&tail_list, &argp[2]); + eaten = 1; + break; + case '.': + if (rts) + { + if (strcmp(rts, &argp[1]) != 0) + fuerror("Two run-time systems?"); + } + else + { + rts = &argp[1]; + l_add(&head_list, rts); + l_add(&tail_list, rts); + } + eaten = 1; + break; + case 0: + nill_flag++; + eaten++; + hide = YES; + break; + case 'w': + w_flag++; + break; + default: /* The flag is not recognized, put it on the list for the sub-processes */ #ifdef DEBUG - if ( debug ) { - vprint("Flag %s: phase dependent\n",argp) ; - } + if (debug) + { + vprint("Flag %s: phase dependent\n", argp); + } #endif - l_add(&flags,keeps(argp)) ; - eaten=1 ; - hide=YES ; + l_add(&flags, keeps(argp)); + eaten = 1; + hide = YES; } - if ( !hide ) { - register char *tokeep ; - tokeep=keeps(argp) ; - if ( argp[1]=='R' ) { - do_Rflag(tokeep); - } else { - *tokeep |= NO_SCAN ; + if (!hide) + { + register char* tokeep; + tokeep = keeps(argp); + if (argp[1] == 'R') + { + l_add(&R_list, tokeep); } - l_add(&flags,tokeep) ; + else + { + *tokeep |= NO_SCAN; + } + l_add(&flags, tokeep); } - if ( argp[2] && !eaten ) { - werror("Unexpected characters at end of %s",argp) ; + if (argp[2] && !eaten) + { + werror("Unexpected characters at end of %s", argp); } } - return ; + return; } -firstarg(argp) register char *argp ; { - register char *name ; +static void firstarg(char* argp) +{ + register char* name; - name=strrchr(argp,'/') ; - if ( name && *(name+1) ) { - name++ ; - } else { - name= argp ; + name = strrchr(argp, '/'); + if (name && *(name + 1)) + { + name++; } - callname= name; + else + { + name = argp; + } + callname = name; } /************************* argument processing ***********************/ -process(arg) char *arg ; { +static int process(char* arg) +{ /* Process files & library arguments */ - trf *phase ; - register trf *tmp ; + trf* phase; + register trf* tmp; #ifdef DEBUG - if ( debug ) vprint("Processing %s\n",arg) ; + if (debug) + vprint("Processing %s\n", arg); #endif - p_suffix= strrchr(arg,SUFCHAR) ; - orig.p_keep= YES ; /* Don't throw away the original ! */ - orig.p_keeps= NO; - orig.p_path= arg ; - if ( arg[0]=='-' || !p_suffix ) { - if ( linker ) add_input(&orig,linker) ; - return 1 ; + p_suffix = strrchr(arg, SUFCHAR); + orig.p_keep = YES; /* Don't throw away the original ! */ + orig.p_keeps = NO; + orig.p_path = arg; + if (arg[0] == '-' || !p_suffix) + { + if (linker) + add_input(&orig, linker); + return 1; } - if ( p_basename ) throws(p_basename) ; - p_basename= keeps(basename(arg)) ; + if (p_basename) + throws(p_basename); + p_basename = keeps(ack_basename(arg)); /* Try to find a path through the transformations */ - switch( getpath(&phase) ) { - case F_NOPATH : - error("Cannot produce the desired file from %s",arg) ; - if ( linker ) add_input(&orig,linker) ; - return 1 ; - case F_NOMATCH : - if ( stopsuffix ) werror("Unknown suffix in %s",arg) ; - if ( linker ) add_input(&orig,linker) ; - return 1 ; - case F_OK : - break ; + switch (getpath(&phase)) + { + case F_NOPATH: + error("Cannot produce the desired file from %s", arg); + if (linker) + add_input(&orig, linker); + return 1; + case F_NOMATCH: + if (stopsuffix) + werror("Unknown suffix in %s", arg); + if (linker) + add_input(&orig, linker); + return 1; + case F_OK: + break; } - if ( !phase ) return 1 ; - for ( tmp=phase ; tmp ; tmp=tmp->t_next ) - if ( !tmp->t_visited ) { - /* The flags are set up once. + if (!phase) + return 1; + for (tmp = phase; tmp; tmp = tmp->t_next) + if (!tmp->t_visited) + { + /* The flags are set up once. At the first time each phase is in a list. The program name and flags may already be touched by vieuwargs. */ - tmp->t_visited=YES ; - if ( tmp->t_priority<0 ) - werror("Using phase %s (negative priority)", - tmp->t_name) ; - if ( !rts && tmp->t_rts ) rts= tmp->t_rts ; - if ( tmp->t_needed ) { - add_head(tmp->t_needed) ; - add_tail(tmp->t_needed) ; + tmp->t_visited = YES; + if (tmp->t_priority < 0) + werror("Using phase %s (negative priority)", + tmp->t_name); + if (!rts && tmp->t_rts) + rts = tmp->t_rts; + if (tmp->t_needed) + { + add_head(tmp->t_needed); + add_tail(tmp->t_needed); + } } + if (phase->t_combine) + { + add_input(&orig, phase); + return 1; } - if ( phase->t_combine ) { - add_input(&orig,phase) ; - return 1 ; - } - in= orig ; - if ( !nill_flag && arg_count > 1 ) { - printf("%s\n",arg) ; - } - return startrf(phase) ; + in = orig; + return startrf(phase); } -int startrf(first) trf *first ; { +static int startrf(trf* first) +{ /* Start the transformations at the indicated phase */ - register trf *phase ; + register trf* phase; - phase=first ; - for(;;) { + phase = first; + for (;;) + { int do_preprocess = 0; int only_prep = 0; - switch ( phase->t_prep ) { + switch (phase->t_prep) + { /* BEWARE, sign extension */ - case NO : break ; - default : if ( !mayprep() ) break ; - case YES: do_preprocess = 1; - break; + case NO: + break; + default: + if (!mayprep()) + break; + case YES: + do_preprocess = 1; + break; } - if ( cpp_trafo && stopsuffix && - strcmp(cpp_trafo->t_out,stopsuffix)==0 ) { + if (cpp_trafo && stopsuffix && strcmp(cpp_trafo->t_out, stopsuffix) == 0) + { /* user explicitly asked for preprocessing */ do_preprocess = 1; only_prep = 1; } - if (do_preprocess && !transform(cpp_trafo) ) { - n_error++ ; + if (do_preprocess && !transform(cpp_trafo)) + { + n_error++; #ifdef DEBUG - vprint("Pre-processor failed\n") ; + vprint("Pre-processor failed\n"); #endif - return 0 ; + return 0; } - if ( only_prep ) { - break ; + if (only_prep) + { + break; } - if ( !transform(phase) ) { - n_error++ ; - block(phase->t_next) ; + if (!transform(phase)) + { + n_error++; + block(phase->t_next); #ifdef DEBUG - if ( debug ) { - if ( !orig.p_path ) { + if (debug) + { + if (!orig.p_path) + { vprint("phase %s failed\n", - phase->t_name ) ; - } else { + phase->t_name); + } + else + { vprint("phase %s for %s failed\n", - phase->t_name,orig.p_path) ; + phase->t_name, orig.p_path); } } #endif - return 0 ; + return 0; } - first=NO ; - phase=phase->t_next ; - if ( !phase ) { + first = NO; + phase = phase->t_next; + if (!phase) + { #ifdef DEBUG -if ( debug ) vprint("Transformation sequence complete for %s\n", - orig.p_path) ; + if (debug) + vprint("Transformation sequence complete for %s\n", + orig.p_path); #endif /* No more work on this file */ - if ( !in.p_keep ) { - fatal("attempt to discard the result file") ; + if (!in.p_keep) + { + fatal("attempt to discard the result file"); } - if ( in.p_keeps ) throws(in.p_path) ; - in.p_keep=NO ; in.p_keeps=NO ; in.p_path= (char *) 0 ; - return 1 ; + if (in.p_keeps) + throws(in.p_path); + in.p_keep = NO; + in.p_keeps = NO; + in.p_path = (char*)0; + return 1; } - if ( phase->t_combine ) { - add_input(&in,phase) ; - break ; + if (phase->t_combine) + { + add_input(&in, phase); + break; } } - return 1 ; + return 1; } -block(first) trf *first ; { +static void block(trf* first) +{ /* One of the input files of this phase could not be produced, block all combiners taking their input from this one. */ - register trf *phase ; - for ( phase=first ; phase ; phase=phase->t_next ) { - if ( phase->t_combine ) phase->t_blocked=YES ; + register trf* phase; + for (phase = first; phase; phase = phase->t_next) + { + if (phase->t_combine) + phase->t_blocked = YES; } } -mayprep() { - int file ; - char fc ; - file=open(in.p_path,0); - if ( file<0 ) return 0 ; - if ( read(file,&fc,1)!=1 ) fc=0 ; - close(file) ; - return fc=='#' ; + +static int mayprep(void) +{ + int file; + char fc; + file = open(in.p_path, 0); + if (file < 0) + return 0; + if (read(file, &fc, 1) != 1) + fc = 0; + close(file); + return fc == '#'; } -keephead(suffix) char *suffix ; { - l_add(&head_list, suffix) ; +static void scanneeds(void) +{ + register list_elem* elem; + scanlist(l_first(head_list), elem) { setneeds(l_content(*elem), 0); } + l_clear(&head_list); + scanlist(l_first(tail_list), elem) { setneeds(l_content(*elem), 1); } + l_clear(&tail_list); } -keeptail(suffix) char *suffix ; { - l_add(&tail_list, suffix) ; -} +static void setneeds(const char* suffix, int tail) +{ + trf* phase; -scanneeds() { - register list_elem *elem ; - scanlist(l_first(head_list), elem) { setneeds(l_content(*elem),0) ; } - l_clear(&head_list) ; - scanlist(l_first(tail_list), elem) { setneeds(l_content(*elem),1) ; } - l_clear(&tail_list) ; -} - -setneeds(suffix,tail) char *suffix ; { - trf *phase ; - - p_suffix= suffix ; - switch ( getpath(&phase) ) { - case F_OK : - for ( ; phase ; phase= phase->t_next ) { - if ( phase->t_needed ) { - if ( tail ) - add_tail(phase->t_needed) ; - else - add_head(phase->t_needed) ; + p_suffix = suffix; + switch (getpath(&phase)) + { + case F_OK: + for (; phase; phase = phase->t_next) + { + if (phase->t_needed) + { + if (tail) + add_tail(phase->t_needed); + else + add_head(phase->t_needed); + } } - } - break ; - case F_NOMATCH : - werror("\"%s\": unrecognized suffix",suffix) ; - break ; - case F_NOPATH : - werror("sorry, cannot produce the desired file(s) from %s files", - suffix) ; - break ; + break; + case F_NOMATCH: + werror("\"%s\": unrecognized suffix", suffix); + break; + case F_NOPATH: + werror("sorry, cannot produce the desired file(s) from %s files", + suffix); + break; } } + +static void noodstop(int sig) +{ + quit(-3); +} diff --git a/util/ack/rmach.c b/util/ack/rmach.c index 1e33e8713..13f904a38 100644 --- a/util/ack/rmach.c +++ b/util/ack/rmach.c @@ -47,19 +47,17 @@ static char rcs_dmach[] = RCS_DMACH ; #define CALL "callname" #define END "end" -extern growstring scanb(); -extern growstring scanvars(); +static void intrf(void) ; +static void open_in(char *) ; +static void close_in(void) ; +static int getinchar(void) ; +static int getln(void) ; -int getln() ; -int getinchar() ; static char *ty_name ; static char *bol ; - -void open_in(); - static char *inname ; -setlist(name) char *name ; { +void setlist(char *name) { /* Name is sought in the internal tables, if not present, the a file of that name is sought in first the current and then the EM Lib directory @@ -92,9 +90,7 @@ setlist(name) char *name ; { #endif } -static int inoptlist(nm) - char *nm ; -{ +static int inoptlist(char *nm) { register char *p=Optlist ; while ( p && *p ) { @@ -107,9 +103,9 @@ static int inoptlist(nm) return 0; } -intrf() { +static void intrf(void) { + /* Read in trf (transformation) */ register trf *new ; - growstring bline ; int twice ; int name_seen=0 ; @@ -130,20 +126,14 @@ intrf() { } else if ( strcmp(ty_name,PROG)==0 ) { if ( new->t_prog ) twice=YES ; - bline= scanb(bol); /* Scan for \ */ - new->t_prog= gr_final(&bline); + new->t_prog= keeps(bol); } else if ( strcmp(ty_name,MAPF)==0 ) { - /* First read the mapflags line - and scan for backslashes */ - bline= scanb(bol) ; - l_add(&new->t_mapf,gr_final(&bline)) ; + l_add(&new->t_mapf,keeps(bol)) ; } else if ( strcmp(ty_name,ARGS)==0 ) { if ( new->t_argd ) twice=YES ; - bline= scanb(bol) ; - new->t_argd= keeps(gr_start(bline)) ; - gr_throw(&bline) ; + new->t_argd= keeps(bol) ; } else if ( strcmp(ty_name,STD_IN)==0 ) { if ( new->t_stdin ) twice=YES ; @@ -234,14 +224,15 @@ intrf() { rts, new->t_rts) ; } rts= new->t_rts ; - keephead(rts) ; keeptail(rts) ; + l_add(&head_list, rts) ; + l_add(&tail_list, rts) ; } #ifdef DEBUG if ( debug>=3 ) { register list_elem *elem ; vprint("%s: from %s to %s '%s'\n", new->t_name,new->t_in ? new->t_in : "(null)",new->t_out,new->t_prog) ; - vprint("\targs: ") ; prns(new->t_argd) ; + vprint("\targs: %s",new->t_argd) ; scanlist( l_first(new->t_mapf), elem ) { vprint("\t%s\n",l_content(*elem)) ; } @@ -264,8 +255,7 @@ static FILE *infile ; static char *inptr ; char *em_dir = EM_DIR; -void -open_in(name) register char *name ; { +static void open_in(char *name) { register dmach *cmac ; gr_init(&rline) ; @@ -298,12 +288,12 @@ open_in(name) register char *name ; { } } -close_in() { +static void close_in(void) { if ( !incore ) fclose(infile) ; gr_throw(&rline) ; } -char *readline() { +static char *readline(void) { /* Get a line from the input, return 0 if at end, The line is stored in a volatile buffer, @@ -355,7 +345,7 @@ char *readline() { } } -int getinchar() { +static int getinchar(void) { register int token ; if ( incore ) { @@ -369,7 +359,7 @@ int getinchar() { return token ; } -int getln() { +static int getln(void) { register char *c_ptr ; do { diff --git a/util/ack/run.c b/util/ack/run.c index 8d0481a58..32cb59fe5 100644 --- a/util/ack/run.c +++ b/util/ack/run.c @@ -5,6 +5,7 @@ */ #include +#include #include #include "ack.h" #include "list.h" @@ -19,19 +20,18 @@ static char rcs_id[] = "$Id$" ; #define ARG_MORE 40 /* The size of args chunks to allocate */ -extern growstring scanvars(); +static int run_exec(trf *, const char *); +static void x_arg(char *); static char **arglist ; /* The first argument */ static unsigned argcount ; /* The current number of arguments */ static unsigned argmax; /* The maximum number of arguments so far */ -int runphase(phase) register trf *phase ; { +int runphase(trf *phase) { register list_elem *elem ; - char *prog ; int result ; - growstring bline ; + char *prog ; int result ; - bline=scanvars(phase->t_prog) ; - prog=gr_final(&bline) ; + prog=phase->t_prog ; if ( v_flag || debug ) { if ( v_flag==1 && !debug ) { vprint("%s",phase->t_name) ; @@ -65,16 +65,19 @@ int runphase(phase) register trf *phase ; { x_arg(l_content(*elem)) ; } x_arg( (char *)0 ) ; - result=run_exec(phase,prog) ; - throws(prog) ; - return result ; + result=run_exec(phase,prog) ; + return result ; } -int run_exec(phase,prog) trf *phase ; char *prog ; { +static int run_exec(trf *phase, const char *prog) { int status, child, waitchild ; - do_flush(); - while ( (child=fork())== -1 ) ; + fflush(stdout) ; + fflush(stderr) ; + child= fork() ; + if ( child== - 1) { + fatal("Cannot fork %s", prog) ; + } if ( child ) { /* The parent */ do { @@ -84,8 +87,6 @@ int run_exec(phase,prog) trf *phase ; char *prog ; { } } while ( waitchild!=child) ; if ( status ) { - if ( status&0200 && (status&0177)!=SIGQUIT && - t_flag<=1 ) unlink("core") ; switch ( status&0177 ) { case 0 : break ; @@ -136,7 +137,7 @@ int run_exec(phase,prog) trf *phase ; char *prog ; { /*NOTREACHED*/ } -x_arg(string) char *string ; { +static void x_arg(char *string) { /* Add one execute argument to the argument vector */ if ( argcount==argmax ) { if ( argmax==0 ) { diff --git a/util/ack/scan.c b/util/ack/scan.c index d020e6a5b..3aaab8492 100644 --- a/util/ack/scan.c +++ b/util/ack/scan.c @@ -15,9 +15,14 @@ static char rcs_id[] = "$Id$" ; #endif -void try(); +static void start_scan(void); +static void try(list_elem *, const char *); +static void scan_found(void); +static int satisfy(trf *, const char *); +static enum f_path scan_end(trf **); +static void find_cpp(void); -enum f_path getpath(first) register trf **first ; { +enum f_path getpath(trf **first) { /* Try to find a transformation path */ start_scan(); @@ -49,7 +54,7 @@ static int suf_found; /* Was the suffix at least recognized ? */ /******************** The hard work ********************/ -start_scan() { +static void start_scan(void) { register list_elem *scan ; scanlist(l_first(tr_list),scan) { @@ -63,8 +68,7 @@ start_scan() { last_ocount= 0 ; } -void -try(f_scan,suffix) list_elem *f_scan; char *suffix; { +static void try(list_elem *f_scan, const char *suffix) { register list_elem *scan ; register trf *trafo ; /* Try to find a transformation path starting at f_scan for a @@ -134,7 +138,7 @@ try(f_scan,suffix) list_elem *f_scan; char *suffix; { } } -scan_found() { +static void scan_found(void) { register list_elem *scan; int ncount, ocount, pcount ; @@ -182,7 +186,7 @@ scan_found() { } } -int satisfy(trafo,suffix) register trf *trafo; char *suffix ; { +static int satisfy(trf *trafo, const char *suffix) { register char *f_char, *l_char ; /* Check whether this transformation is present for the current machine and the parameter suffix is among @@ -207,7 +211,7 @@ int satisfy(trafo,suffix) register trf *trafo; char *suffix ; { return 0 ; } -enum f_path scan_end(first) trf **first ; { /* Finalization */ +static enum f_path scan_end(trf **first) { /* Finalization */ /* Return value indicating whether a transformation was found */ /* Set the flags for the transformation up to, but not including, the combiner @@ -248,7 +252,7 @@ enum f_path scan_end(first) trf **first ; { /* Finalization */ return F_OK ; } -find_cpp() { +static void find_cpp(void) { register list_elem *elem ; scanlist( l_first(tr_list), elem ) { if ( t_cont(*elem)->t_isprep ) { diff --git a/util/ack/svars.c b/util/ack/svars.c index 2d7e4b42c..e540e5d02 100644 --- a/util/ack/svars.c +++ b/util/ack/svars.c @@ -4,6 +4,7 @@ * */ +#include #include "ack.h" #ifndef NORCSID @@ -44,9 +45,6 @@ static char rcs_id[] = "$Id$" ; */ -extern char *getcore(); -extern fatal(); - struct vars { char *v_name; enum { routine, string } v_type; @@ -60,7 +58,7 @@ struct vars { static struct vars *v_first ; -static struct vars *newvar(name) char *name; { +static struct vars *newvar(char *name) { register struct vars *new ; for ( new=v_first ; new ; new= new->v_next ) { @@ -72,36 +70,36 @@ static struct vars *newvar(name) char *name; { return new ; } } - new= (struct vars *)getcore( (unsigned)sizeof (struct vars)); + new= (struct vars *)getcore(sizeof (struct vars)); new->v_name= name ; new->v_next= v_first ; v_first= new ; return new ; } -setsvar(name,str) char *name, *str ; { +void setsvar(char *name, char *str) { register struct vars *new ; new= newvar(name); #ifdef DEBUG - if ( debug>=2 ) vprint("%s=%s\n", name, str) ; + if ( debug>=2 ) vprint("%s=%s\n", new->v_name, str) ; #endif new->v_type= string; new->v_value.v_string= str; } -setpvar(name,rout) char *name, *(*rout)() ; { +void setpvar(char *name, char *(*rout)(void)) { register struct vars *new ; new= newvar(name); #ifdef DEBUG - if ( debug>=2 ) vprint("%s= (*%o)()\n",name,rout) ; + if ( debug>=2 ) vprint("%s= (*%o)()\n", new->v_name, rout) ; #endif new->v_type= routine; new->v_value.v_routine= rout; } -char *getvar(name) char *name ; { +char *getvar(const char *name) { register struct vars *scan ; for ( scan=v_first ; scan ; scan= scan->v_next ) { diff --git a/util/ack/trans.c b/util/ack/trans.c index 3cb2d7ea8..98a75a066 100644 --- a/util/ack/trans.c +++ b/util/ack/trans.c @@ -26,13 +26,17 @@ static int touch_head= NO ; static growstring tail ; static int touch_tail= NO ; -char *headvar(),*tailvar() ; +static char *headvar(void); +static char *tailvar(void); +static void set_Rflag(char *); +static void condit(growstring *, list_head *, list_head *, char *); +static int mapflag(list_head *, const char *); +static int mapexpand(char *, const char *); +static void getcallargs(trf *); +static growstring without_bslash(const char *); +static void getprogram(trf *); -void condit(); -void doassign(); -void set_Rflag(); - -int transform(phase) register trf *phase ; { +int transform(trf *phase) { int ok ; if ( !setfiles(phase) ) { @@ -40,17 +44,19 @@ int transform(phase) register trf *phase ; { return 0 ; } getcallargs(phase) ; + getprogram(phase) ; ok= runphase(phase) ; if ( !ok ) rmfile(&out) ; /* Free the space occupied by the arguments, except for the linker, since we are bound to exit soon and do not foresee further need of memory space */ - if ( !phase->t_linker ) discardargs(phase) ; + if ( !phase->t_linker ) + l_throw(&phase->t_args) ; disc_files(phase) ; return ok ; } -getmapflags(phase) register trf *phase ; { +void getmapflags(trf *phase) { register path *l_in ; register list_elem *elem ; int scanned ; @@ -75,8 +81,9 @@ getmapflags(phase) register trf *phase ; { scanlist(l_first(phase->t_inputs),elem) { l_in = p_cont(*elem) ; if ( mapflag(&(phase->t_mapf),l_in->p_path) ) { - ptr= keeps(getvar(LIBVAR)) ; - clr_noscan(ptr) ; + growstring temp; + temp= without_bslash(getvar(LIBVAR)) ; + ptr= gr_final(&temp); #ifdef DEBUG if ( debug >=4 ) { vprint("phase %s, library %s(%s)\n", @@ -110,16 +117,12 @@ getmapflags(phase) register trf *phase ; { } -do_Rflag(argp) char *argp ; { - l_add(&R_list,argp) ; -} - -char *headvar() { +static char *headvar(void) { if ( !touch_head) return "" ; return gr_start(head) ; } -add_head(str) char *str; { +void add_head(const char *str) { if ( !touch_head) { gr_init(&head) ; touch_head=YES ; @@ -127,12 +130,12 @@ add_head(str) char *str; { gr_cat(&head,str) ; } -char *tailvar() { +static char *tailvar(void) { if ( !touch_tail ) return "" ; return gr_start(tail) ; } -add_tail(str) char *str ; { +void add_tail(const char *str) { if ( !touch_tail ) { gr_init(&tail) ; touch_tail=YES ; @@ -141,7 +144,7 @@ add_tail(str) char *str ; { } -transini() { +void transini(void) { register list_elem *elem ; register trf *phase ; @@ -157,8 +160,7 @@ transini() { setpvar(keeps(TAIL),tailvar) ; } -void -set_Rflag(argp) register char *argp ; { +static void set_Rflag(char *argp) { register char *eos ; register list_elem *prog ; register int length ; @@ -206,72 +208,47 @@ set_Rflag(argp) register char *argp ; { /* */ /**************************************************************************/ -growstring scanb(line) char *line ; { - /* Scan a line for backslashes, setting the NO_SCAN bit in characters - preceded by a backslash. - */ - register char *in_c ; - register int token ; - growstring result ; - enum { TEXT, ESCAPED } state = TEXT ; - - gr_init(&result) ; - for ( in_c= line ; *in_c ; in_c++ ) { - token= *in_c&0377 ; - switch( state ) { - case TEXT : - if ( token==BSLASH ) { - state= ESCAPED ; - } else { - gr_add(&result,token) ; - } - break ; - case ESCAPED : - gr_add(&result,token|NO_SCAN) ; - state=TEXT ; - break ; - } - } - gr_add(&result,0) ; - if ( state!=TEXT ) werror("flag line ends with %c",BSLASH) ; - return result ; -} - -growstring scanvars(line) char *line ; { +static growstring scanvars(const char *line) { /* Scan a line variable replacements started by S_VAR. - Two sequences exist: S_VAR name E_VAR, S_VAR name A_VAR text E_VAR. + Two sequences exist: S_VAR name C_VAR, S_VAR name A_VAR text C_VAR. neither name nor text may contain further replacements. In the first form an error message is issued if the name is not present in the variables, the second form produces text in that case. - The sequence S_VAR S_VAR is transformed into S_VAR. - This to allow later recognition in mapflags, where B_SLASH - would be preventing any recognition. */ - register char *in_c ; - register int token ; - growstring result ; - growstring name ; - register char *tr ; + const char *in_c ; + int token, token_r ; + growstring result, name ; + char *tr ; enum { TEXT, FIRST, NAME, SKIP, COPY } state = TEXT ; + int escaped = NO; gr_init(&result) ; gr_init(&name) ; for ( in_c= line ; *in_c ; in_c++ ) { token= *in_c&0377 ; + token_r= (escaped ? 0 : token); + + /* A backslash escapes the next character. */ + if ( token_r==BSLASH ) { + if ( state==TEXT || state==COPY ) { + /* Keep BSLASH for later scans. */ + gr_add(&result,token) ; + } + escaped= YES; + continue; + } + escaped= NO; + switch( state ) { case TEXT : - if ( token==S_VAR ) { + if ( token_r==S_VAR ) { state= FIRST ; } else { gr_add(&result,token) ; } break ; case FIRST : - switch ( token ) { - case S_VAR : - state= TEXT ; - gr_add(&result,token) ; - break ; + switch ( token_r ) { case A_VAR : case C_VAR : fatal("empty string variable name") ; @@ -282,7 +259,7 @@ growstring scanvars(line) char *line ; { } break ; case NAME: - switch ( token ) { + switch ( token_r ) { case A_VAR : gr_add(&name,0) ; if ( tr=getvar(gr_start(name)) ) { @@ -314,16 +291,17 @@ growstring scanvars(line) char *line ; { } break ; case SKIP : - if ( token==C_VAR ) state= TEXT ; + if ( token_r==C_VAR ) state= TEXT ; break ; case COPY : - if ( token==C_VAR ) state= TEXT ; else { + if ( token_r==C_VAR ) state= TEXT ; else { gr_add(&result,token) ; } break ; } } gr_add(&result,0) ; + if ( escaped ) werror("flag line ends with %c",BSLASH) ; if ( state!=TEXT ) { werror("flag line misses %c",C_VAR) ; gr_throw(&name) ; @@ -331,74 +309,84 @@ growstring scanvars(line) char *line ; { return result ; } -growstring scanexpr(line) char *line ; { +static growstring scanexpr(const char *line) { /* Scan a line for conditional or flag expressions, dependent on the type. The format is S_EXPR suflist M_EXPR suflist T_EXPR tail C_EXPR - the head and tail are passed to treat, together with the + the head and tail are passed to condit(), together with the growstring for futher treatment. Nesting is not allowed. */ - register char *in_c ; - char *heads ; - register int token ; - growstring sufs, tailval ; - growstring result ; + const char *in_c, *heads ; + int token, token_r ; + growstring sufs, tailval, result ; static list_head fsuff, lsuff ; enum { TEXT, FDOT, FSUF, LDOT, LSUF, FTAIL } state = TEXT ; + int escaped = NO; gr_init(&result) ; gr_init(&sufs) ; gr_init(&tailval) ; for ( in_c= line ; *in_c ; in_c++ ) { token= *in_c&0377 ; + token_r= (escaped ? 0 : token); + + /* A backslash escapes the next character. */ + if ( token_r==BSLASH ) { + if ( state==TEXT || state==FTAIL ) { + /* Keep BSLASH for later scans. */ + gr_add(&result,token) ; + } + escaped= YES; + continue; + } + escaped= NO; + switch( state ) { case TEXT : - if ( token==S_EXPR ) { + if ( token_r==S_EXPR ) { state= FDOT ; heads=in_c ; } else gr_add(&result,token) ; break ; case FDOT : - if ( token==M_EXPR ) { + if ( token_r==M_EXPR ) { state=LDOT ; break ; } - token &= ~NO_SCAN ; if ( token!=SUFCHAR ) { error("Missing %c in expression",SUFCHAR) ; } gr_add(&sufs,token) ; state=FSUF ; break ; case FSUF : - if ( token==M_EXPR || (token&~NO_SCAN)==SUFCHAR) { + if ( token_r==M_EXPR || token==SUFCHAR ) { gr_add(&sufs,0) ; l_add(&fsuff,gr_final(&sufs)) ; } - if ( token==M_EXPR ) { + if ( token_r==M_EXPR ) { state=LDOT ; - } else gr_add(&sufs,token&~NO_SCAN) ; + } else gr_add(&sufs,token) ; break ; case LDOT : - if ( token==T_EXPR ) { + if ( token_r==T_EXPR ) { state=FTAIL ; break ; } - token &= ~NO_SCAN ; if ( token!=SUFCHAR ) { error("Missing %c in expression",SUFCHAR) ; } gr_add(&sufs,token) ; state=LSUF ; break ; case LSUF : - if ( token==T_EXPR || (token&~NO_SCAN)==SUFCHAR) { + if ( token_r==T_EXPR || token==SUFCHAR) { gr_add(&sufs,0) ; l_add(&lsuff,gr_final(&sufs)) ; } - if ( token==T_EXPR ) { + if ( token_r==T_EXPR ) { state=FTAIL ; - } else gr_add(&sufs,token&~NO_SCAN) ; + } else gr_add(&sufs,token) ; break ; case FTAIL : - if ( token==C_EXPR ) { + if ( token_r==C_EXPR ) { /* Found one !! */ gr_add(&tailval,0) ; condit(&result,&fsuff,&lsuff,gr_start(tailval)) ; @@ -418,10 +406,8 @@ growstring scanexpr(line) char *line ; { return result ; } -void -condit(line,fsuff,lsuff,tailval) growstring *line ; - list_head *fsuff, *lsuff; - char *tailval ; +static void condit(growstring *line, list_head *fsuff, list_head *lsuff, + char *tailval) { register list_elem *first ; register list_elem *last ; @@ -446,7 +432,7 @@ condit(line,fsuff,lsuff,tailval) growstring *line ; #endif } -int mapflag(maplist,cflag) list_head *maplist ; char *cflag ; { +static int mapflag(list_head *maplist, const char *cflag) { /* Expand a flag expression */ /* The flag "cflag" is checked for each of the mapflags. A mapflag entry has the form @@ -468,12 +454,9 @@ int mapflag(maplist,cflag) list_head *maplist ; char *cflag ; { return 0 ; } -int mapexpand(mapentry,cflag) - char *mapentry, *cflag ; -{ - register char *star ; - register char *ptr ; - register char *space ; +static int mapexpand(char *mapentry, const char *cflag) { + const char *star ; + char *ptr, *space ; int length ; star=strchr(mapentry,STAR) ; @@ -510,10 +493,10 @@ int mapexpand(mapentry,cflag) return 1 ; } -void -doassign(line,star,length) char *line, *star ; { +void doassign(const char *line, const char *star, int length) { growstring varval, name, temp ; - register char *ptr ; + const char *ptr ; + int escaped = NO ; gr_init(&varval) ; gr_init(&name) ; @@ -528,12 +511,21 @@ doassign(line,star,length) char *line, *star ; { } temp= scanvars(ptr+1) ; for ( ptr=gr_start(temp); *ptr; ptr++ ) switch ( *ptr ) { + case BSLASH : + escaped= YES ; + gr_add(&varval,*ptr) ; + break ; case STAR : - if ( star ) { - while ( length-- ) gr_add(&varval,*star++|NO_SCAN) ; + if ( star && !escaped ) { + while ( length-- ) { + gr_add(&varval,BSLASH) ; + gr_add(&varval,*star++) ; + } break ; } + /* FALLTHROUGH */ default : + escaped= NO ; gr_add(&varval,*ptr) ; break ; } @@ -544,15 +536,16 @@ doassign(line,star,length) char *line, *star ; { #define ISBLANK(c) ( (c)==SPACE || (c)==TAB ) -unravel(line,action) char *line ; int (*action)() ; { +static void unravel(const char *line, void (*action)(char *)) { /* Unravel the line, get arguments a la shell */ /* each argument is handled to action */ /* The input string is left intact */ - register char *in_c ; - register int token ; - enum { BLANK, ARG } state = BLANK ; + const char *in_c ; + int token ; + enum { BLANK, ARG, ESCAPED } state = BLANK ; growstring argum ; + /* Loop for each character of line, including final '\0' */ in_c=line ; for (;;) { token= *in_c&0377 ; @@ -560,9 +553,13 @@ unravel(line,action) char *line ; int (*action)() ; { case BLANK : if ( token==0 ) break ; if ( !ISBLANK(token) ) { - state= ARG ; gr_init(&argum) ; - gr_add(&argum,token&~NO_SCAN) ; + gr_add(&argum,token) ; + if ( token == BSLASH ) { + state= ESCAPED ; + } else { + state= ARG ; + } } break ; case ARG : @@ -572,97 +569,106 @@ unravel(line,action) char *line ; int (*action)() ; { gr_throw(&argum) ; state=BLANK ; } else { - gr_add(&argum,token&~NO_SCAN) ; + gr_add(&argum,token) ; + if ( token == BSLASH ) state= ESCAPED ; } break ; + case ESCAPED : + gr_add(&argum,token) ; + state= ARG ; + break ; } if ( token == 0 ) break ; in_c++ ; } } -char *c_rep(string,place,rep) char *string, *place, *rep ; { - /* Produce a string in stable storage produced from 'string' - with the character at place replaced by rep - */ - growstring name ; - register char *nc ; - register char *xc ; - - gr_init(&name) ; - for ( nc=string ; *nc && ncp_path)) ; + gr_init(&argum); + for ( in_c= prefix1 ; *in_c ; in_c++ ) { + gr_add(&argum,*in_c) ; + } + for ( in_c= prefix2 ; *in_c ; in_c++ ) { + gr_add(&argum,*in_c) ; + } + for ( in_c= string ; *in_c ; in_c++ ) { + token= *in_c&0377 ; + if ( escaped ) { + /* Strip BSLASH, keep escaped character. */ + gr_add(&argum,token) ; + escaped= NO ; + continue; + } + switch ( token ) { + case BSLASH: + escaped= YES ; + break; + case C_IN: /* Input file */ + if ( in.p_path ) { /* Not for the combiners */ + for ( tr= in.p_path ; *tr; tr++ ) { + gr_add(&argum,*tr); } + } else { /* For the combiners */ + gr_add(&argum,0); + tr= gr_final(&argum); + in_c++; + scanlist( l_first(*comb_args), elem ) { + char *p = p_cont(*elem)->p_path ; + addargs3(tr,p,in_c) ; + } + throws(tr); + return; } - return ; - } - if ( in.p_path ) { /* Not for the combiners */ - temp=c_rep(string,repc,in.p_path) ; - addargs(temp) ; - throws(temp) ; - } else { /* For the combiners */ - scanlist( l_first(*comb_args), elem ) { - temp=c_rep(string,repc,p_cont(*elem)->p_path); - addargs(temp) ; - throws(temp) ; - } - } - return ; - } - repc=strchr(string,C_OUT) ; - if ( repc ) { - /* replace the outfile token as with the infile token */ + break; + case C_OUT: /* Output file */ #ifdef DEBUG - if ( !out.p_path ) fatal("missing output filename") ; + if ( !out.p_path ) fatal("missing output filename") ; #endif - temp=c_rep(string,repc,out.p_path) ; - addargs(temp) ; - throws(temp) ; - return ; + for ( tr= out.p_path ; *tr ; tr++ ) { + gr_add(&argum,*tr) ; + } + break; + default: + gr_add(&argum,token) ; + break; + } } - temp= keeps(string) ; - clr_noscan(temp) ; - l_add(curargs,temp) ; + gr_add(&argum,0) ; + tr= gr_final(&argum) ; + l_add(curargs,tr) ; } -getcallargs(phase) register trf *phase ; { +static void addargs(char *string) { + addargs3("", "", string) ; +} + +static void getcallargs(trf *phase) { growstring arg1, arg2 ; arg1= scanvars(phase->t_argd) ; #ifdef DEBUG - if ( debug>=3 ) { vprint("\tvars: ") ; prns(gr_start(arg1)) ; } + if ( debug>=3 ) vprint("\tvars: %s", gr_start(arg1)) ; #endif arg2= scanexpr(gr_start(arg1)) ; #ifdef DEBUG - if ( debug>=3 ) { vprint("\texpr: ") ; prns(gr_start(arg2)) ; } + if ( debug>=3 ) vprint("\texpr: %s", gr_start(arg2)) ; #endif gr_throw(&arg1) ; curargs= &phase->t_args ; @@ -671,6 +677,39 @@ getcallargs(phase) register trf *phase ; { gr_throw(&arg2) ; } -discardargs(phase) register trf *phase ; { - l_throw(&phase->t_args) ; +static growstring without_bslash(const char *string) { + /* Strip backslashes from a copy of the string. */ + growstring result; + const char *in_c ; + int token ; + int escaped = NO ; + + gr_init(&result) ; + for ( in_c= string ; *in_c ; in_c++ ) { + token= *in_c&0377 ; + if ( token==BSLASH && !escaped ) { + escaped= YES ; + } else { + gr_add(&result,token); + escaped= NO ; + } + } + gr_add(&result,0); + return result; +} + +static void getprogram(trf *phase) { + growstring prog1, prog2 ; + const char *in_c ; + int token ; + int escaped = NO ; + + /* Expand string variables in program name. */ + prog1= scanvars(phase->t_prog) ; + throws(phase->t_prog) ; + + /* Strip backslashes. */ + prog2= without_bslash(gr_start(prog1)); + gr_throw(&prog1); + phase->t_prog= gr_final(&prog2); } diff --git a/util/ack/trans.h b/util/ack/trans.h index 70be80832..54086a563 100644 --- a/util/ack/trans.h +++ b/util/ack/trans.h @@ -44,3 +44,26 @@ struct transform { } ; #define t_cont(elem) ((trf *)l_content(elem)) + +/* files.c */ +int setfiles(trf *); +void disc_files(trf *); +void disc_inputs(trf *); +void rmfile(path *); +void rmtemps(void); +void add_input(path *, trf *); + +/* run.c */ +int runphase(trf *); + +/* scan.c */ +enum f_path { F_OK, F_NOMATCH, F_NOPATH } ; +enum f_path getpath(trf **); + +/* trans.c */ +int transform(trf *); +void getmapflags(trf *); +void add_head(const char *); +void add_tail(const char *); +void transini(void); +void doassign(const char *, const char *, int); diff --git a/util/ack/util.c b/util/ack/util.c index 419f087e3..b3754f28e 100644 --- a/util/ack/util.c +++ b/util/ack/util.c @@ -32,15 +32,11 @@ extern int n_error; # define STDOUT stderr #endif -void fuerror(const char* fmt, ...); -void werror(const char* fmt, ...); - -char *basename(string) char *string ; { +char *ack_basename(const char *string) { static char retval[256] ; - char *last_dot, *last_start ; - register char *store; - register char *fetch ; - register int ctoken ; + const char *last_dot, *last_start, *fetch ; + char *store ; + int ctoken ; last_dot= (char *)0 ; last_start= string ; @@ -50,9 +46,6 @@ char *basename(string) char *string ; { case '/' : last_start=fetch+1 ; break ; case 0 : goto out ; } - if ( !isascii(ctoken) || !isprint(ctoken) ) { - werror("non-ascii characters in argument %s",string) ; - } } out: if ( ! *last_start ) fuerror("empty filename \"%s\"",string) ; @@ -65,21 +58,14 @@ out: return retval ; } -clr_noscan(str) char *str ; { - register char *ptr ; - for ( ptr=str ; *ptr ; ptr++ ) { - *ptr&= ~NO_SCAN ; - } -} - -char *skipblank(str) char *str ; { +char *skipblank(char *str) { register char *ptr ; for ( ptr=str ; *ptr==SPACE || *ptr==TAB ; ptr++ ) ; return ptr ; } -char *firstblank(str) char *str ; { +char *firstblank(char *str) { register char *ptr ; for ( ptr=str ; *ptr && *ptr!=SPACE && *ptr!=TAB ; ptr++ ) ; @@ -109,15 +95,6 @@ void vprint(const char* fmt, ...) va_end(ap); } -#ifdef DEBUG -prns(s) register char *s ; { - for ( ; *s ; s++ ) { - putc((*s&0377)&~NO_SCAN,STDOUT) ; - } - putc('\n',STDOUT) ; -} -#endif - /* VARARGS1 */ void fuerror(const char *fmt, ...) { /* Fatal user error */ @@ -153,48 +130,36 @@ void error(const char *fmt, ...) { va_end(ap); } -do_flush() { - fflush(stdout) ; - fflush(stderr) ; -} - -void -noodstop() { - quit(-3) ; -} - -quit(code) { +void quit(int code) { rmtemps(); exit(code); } + /****** char *keeps(string) Keep the string in stable storage. throws(string) Remove the string stored by keep from stable storage. + throws() is now a macro in ack.h. ***********/ -char *keeps(str) char *str ; { +char *keeps(const char *str) { register char *result ; result= getcore( (unsigned)(strlen(str)+1) ) ; if ( !result ) fatal("Out of core") ; return strcpy(result,str) ; } -throws(str) char *str ; { - freecore(str) ; -} - -char *getcore(size) unsigned size ; { - register char *retptr ; +void *getcore(size_t size) { + void *retptr ; retptr= calloc(1,size) ; if ( !retptr ) fatal("Out of memory") ; return retptr ; } -char *changecore(ptr,size) char *ptr ; unsigned size ; { - register char *retptr ; +void *changecore(void *ptr, size_t size) { + void *retptr ; retptr= realloc(ptr,size) ; if ( !retptr ) fatal("Out of memory") ; diff --git a/util/amisc/abmodules.1 b/util/amisc/abmodules.1 new file mode 100644 index 000000000..1eb67d843 --- /dev/null +++ b/util/amisc/abmodules.1 @@ -0,0 +1,25 @@ +.TH ABMODULES 1 2017-01-18 +.SH NAME +abmodules \- find B modules +.SH SYNOPSIS +abmodules [ \-o outputfile.c ] [ file ... ] +.SH DESCRIPTION +.I abmodules +finds B modules in a set of ack.out(5) format object files, and either lists +them or generates a C file which initialises the modules. +.PP +This tool is used for multiple compilation of B programs; B modules must be +initialised before use, and this tool generates the initialisation code for +programs containing an abitrary number of modules. +See em_b(6) for details. +.PP +Options are: +.TP +.B \-o filename +Write C source to +.I filename +containing a definition of a binit() function which will initalise all modules +found. +If not present, a simple list of module names is written to stdout instead. +.SH SEE ALSO +ack.out(5), em_b(6) diff --git a/util/amisc/abmodules.c b/util/amisc/abmodules.c new file mode 100644 index 000000000..e1190c207 --- /dev/null +++ b/util/amisc/abmodules.c @@ -0,0 +1,216 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "out.h" +#include "arch.h" +#include "ranlib.h" +#include "object.h" +#include "diagnostics.h" +#include "stringlist.h" + +int numsort_flg; +int sectsort_flg; +int undef_flg; +int revsort_flg = 1; +int globl_flg; +int nosort_flg; +int arch_flg; +int prep_flg; +int read_error; +struct outsect sbuf; +long off; +long s_base[S_MAX]; /* for specially encoded bases */ +char *filename; +int narg; + +extern int rd_unsigned2(); + +static const char prefix[] = "_bmodule_"; + +static struct stringlist modules; + +static void do_file(int fd) +{ + struct outhead hbuf; + struct outname *nbufp = NULL; + char *cbufp; + long fi_to_co; + long n; + unsigned readcount; + int i,j; + int compare(); + + read_error = 0; + rd_fdopen(fd); + + rd_ohead(&hbuf); + if (BADMAGIC(hbuf)) + return; + + n = hbuf.oh_nname; + if (n == 0) + fatal("%s --- no name list", filename); + + if (hbuf.oh_nchar == 0) + fatal("%s --- no names", filename); + + if ((readcount = hbuf.oh_nchar) != hbuf.oh_nchar) + fatal("%s --- string area too big", filename); + + cbufp = calloc(readcount, 1); + rd_string(cbufp, hbuf.oh_nchar); + if (read_error) + goto corrupt; + + fi_to_co = (long) (cbufp - OFF_CHAR(hbuf)); + while (--n >= 0) + { + struct outname nbuf; + struct stringfragment* f; + + rd_name(&nbuf, 1); + if (read_error) + goto corrupt; + + if (!(nbuf.on_type & S_EXT)) + continue; + if ((nbuf.on_type & S_TYP) == S_UND) + continue; + + if (nbuf.on_foff == 0) + nbuf.on_mptr = 0; + else + nbuf.on_mptr = (char *) (nbuf.on_foff + fi_to_co); + + if (strlen(nbuf.on_mptr) <= sizeof(prefix)) + continue; + if (memcmp(nbuf.on_mptr, prefix, sizeof(prefix)-1) != 0) + continue; + + stringlist_add(&modules, strdup(nbuf.on_mptr + sizeof(prefix) - 1)); + } + + if (cbufp) + free(cbufp); + + return; +corrupt: + fatal("%s --- corrupt", filename); +} + +static void process(int fd) +{ + uint16_t magic = rd_unsigned2(fd); + switch(magic) { + case O_MAGIC: + lseek(fd, 0L, 0); + do_file(fd); + break; + + case ARMAG: + case AALMAG: + { + struct ar_hdr archive_header; + static char buf[sizeof(archive_header.ar_name)+1]; + + while (rd_arhdr(fd, &archive_header)) + { + long nextpos = lseek(fd, 0L, SEEK_CUR) + archive_header.ar_size; + if (nextpos & 1) + nextpos++; + + strncpy(buf, archive_header.ar_name, sizeof(archive_header.ar_name)); + filename = buf; + if (strcmp(filename, SYMDEF) != 0) + do_file(fd); + lseek(fd, nextpos, 0); + } + break; + } + + default: + fatal("file %s is of unknown format", filename); + } +} + +int main(int argc, char* const argv[]) +{ + int opt; + FILE* outputfp = NULL; + + program_name = argv[0]; + for (;;) + { + int opt = getopt(argc, argv, "o:"); + if (opt == -1) + break; + + switch (opt) + { + case 'o': + outputfp = fopen(optarg, "w"); + if (!outputfp) + fatal("cannot open output file: %s", strerror(errno)); + break; + + default: + fatal("usage: abmodules [-o outputfile] [file...]"); + } + } + + for (;;) + { + int fd; + + filename = argv[optind++]; + if (!filename) + break; + if ((fd = open(filename, 0)) < 0) + fatal("cannot open %s: %s", filename, strerror(errno)); + process(fd); + close(fd); + } + + if (outputfp) + { + struct stringfragment* f; + + fprintf(outputfp, "#include \n"); + fprintf(outputfp, "\n"); + + for (f = modules.first; f; f = f->next) + fprintf(outputfp, "extern uintptr_t bmodule_%s[];\n", f->data); + + fprintf(outputfp, "\n"); + fprintf(outputfp, "extern void patch_addresses(uintptr_t* module);\n"); + fprintf(outputfp, "\n"); + fprintf(outputfp, "void binit(void) {\n"); + for (f = modules.first; f; f = f->next) + fprintf(outputfp, "\tpatch_addresses(bmodule_%s);\n", f->data); + fprintf(outputfp, "}\n"); + fclose(outputfp); + } + else + { + struct stringfragment* f; + + for (f = modules.first; f; f = f->next) + printf("%s\n", f->data); + } + + exit(0); +} + +void rd_fatal(void) +{ + fatal("read error on %s", filename); +} diff --git a/util/amisc/aelflod.1 b/util/amisc/aelflod.1 index 24001ba2d..e6af7ef2e 100644 --- a/util/amisc/aelflod.1 +++ b/util/amisc/aelflod.1 @@ -1,25 +1,59 @@ -.TH ASLOD 1 "$Revision$" +.TH AELFLOD 1 2017-01-18 .SH NAME aelflod \- ACK ELF loader .SH SYNOPSIS -aelflod [-h] [-v] inputfile outputfile +.B aelflod +[\-a\fInumber\fP] [\-b] [\-h] [\-l] [\-m\fInumber\fP] [\-v] +inputfile outputfile .SH DESCRIPTION .I aelflod converts an absolute ack.out file into a simple binary memory -dump wrapped up in an ELF executable. It is suitable for producing -executables for operating systems such as Linux. - +dump wrapped up in an ELF executable. +It is suitable for producing executables for operating systems +such as Linux. +.PP +.I aelflod +accepts the following flags: +.TP +.BI \-a number +Set the ABI in the ELF header to \fInumber\fP. +The default value is \fI3\fP for Linux. +.TP +.B \-b +Write a big-endian ELF file. +.TP +.B \-h +Print a help message and exit. +.TP +.B \-l +Write a little-endian ELF file. +This is the default. +.TP +.BI \-m number +Set the machine type in the ELF header to \fInumber\fP. +The default value is \fI3\fP for Intel 386 (i386). +Other values are \fI4\fP for Motorola 68000 (m68k) +and \fI20\fP for PowerPC. +.TP +.B \-v +Be verbose. +.PP The input file must contain exactly four segments: TEXT, ROM, DATA and BSS, in that order, all occupying contiguous memory. The file must have all references resolved and be linked to a -fixed address. The fixed address must be at least 0x54 bytes -greater than a page boundary, in order to make room for the ELF -header itself. - -aelflod will write out an ELF header followed by each segment, in -order, ensuring that enough padding is inserted between each segment -to keep the offsets correct. The created executable will contain just -one rwx segment, and no sections. - +fixed address. +The fixed address must be at least 0x54 bytes greater than a +page boundary, in order to make room for the ELF header itself. +.PP +.I aelflod +will write out an ELF header followed by each segment, in order, +ensuring that enough padding is inserted between each segment +to keep the offsets correct. +The created executable will contain just one ELF segment mapped rwx. +.PP +If the input file has symbols, then +.I aelflod +will convert the symbol table to ELF. +The output file has ELF section headers if and only if it has symbols. .SH "SEE ALSO" ack.out(5) diff --git a/util/amisc/aelflod.c b/util/amisc/aelflod.c index e3692ac01..dbaafc9b5 100644 --- a/util/amisc/aelflod.c +++ b/util/amisc/aelflod.c @@ -35,10 +35,15 @@ int elfabi = 3; /* abi = Linux */ int elfmachine = 3; /* machine = EM_386 */ /* Header and section table of an ack object file. */ - + struct outhead outhead; struct outsect outsect[S_MAX]; +struct outname* outname = NULL; char* stringarea; +uint32_t ack_off_char; +int nstab = 0; /* S_STB symbol count */ +int nsym = 0; /* other symbol count */ +int nlocal = 0; /* local symbols */ char* outputfile = NULL; /* Name of output file, or NULL */ char* program; /* Name of current program: argv[0] */ @@ -49,23 +54,30 @@ FILE* output; /* Output stream */ #define readf(a, b, c) fread((a), (b), (int)(c), input) #define writef(a, b, c) fwrite((a), (b), (int)(c), output) -/* Header and program header table of an ELF object file. */ +/* Contents of an ELF object file. */ #define ELF_HEADER_SIZE 0x34 #define PROGRAM_HEADER_SIZE 0x20 #define PROGRAM_HEADER_COUNT 1 -unsigned long codeoffset; +#define SECTION_HEADER_SIZE 0x28 +#define STAB_SYMBOL_SIZE 12 +#define ELF_SYMBOL_SIZE 16 + +uint32_t code_offset; /* ELF segment */ +uint32_t stab_offset; /* Debugger symbol table */ +uint32_t symtab_offset; /* ELF symbol table */ +uint32_t strtab_offset; /* String table */ +uint32_t shstrtab_offset; /* Section header string table */ +uint32_t sh_offset; /* ELF section headers */ + +int sh_count = 0; /* Number of ELF sections */ +int shstrtab_nr = 0; /* Section number of .shstrtab */ +int shstrtab_size; const char elf_le_ident_string[] = { 0x7F, 'E', 'L', 'F' }; -/* Output file definitions and such */ - -#define HDR_LENGTH 32 - -char hdr[HDR_LENGTH] ; - bool verbose = false; /* Segment numbers understood by aelflod. */ @@ -78,13 +90,33 @@ enum { NUM_SEGMENTS }; -#define N_EXT 040 -#define N_UNDEF 00 -#define N_ABS 01 -#define N_TEXT 02 -#define N_DATA 03 -#define N_BSS 04 -#define N_FN 037 +/* + * ELF section numbers count up in the order that we write the ELF + * section headers. If we have no debugger symbols, we will skip + * .stab and .stabstr, then subtract 2 from all later numbers. + */ +enum { + N_UNDEF = 0, + N_TEXT, + N_RODATA, + N_DATA, + N_BSS, + N_STAB, + N_STABSTR, + N_SYMTAB, + N_STRTAB, + N_SHSTRTAB, + NUM_ELF_SECTIONS, +}; +const char shstrtab[] = + "\0.text\0.rodata\0.data\0.bss\0.stab\0.stabstr\0" + ".symtab\0.strtab\0.shstrtab"; + /* Compiler appends one more "\0". */ +const int sh_name[] = { + /* Index of each name in shstrtab: */ + 0, 1, 7, 15, 21, 26, 32, + 41, 49, 57, +}; /* Produce an error message and exit. */ @@ -121,6 +153,80 @@ int follows(struct outsect* pa, struct outsect* pb) return (pa->os_base >= align(pb->os_base+pb->os_size, pa->os_lign)); } +/* Convert a symbol's name index from ack.out to ELF. */ + +uint32_t cvname(struct outname* n) +{ + if (n->on_foff) { + /* ack.out: offset from beginning of file + * ELF: index in string table + * the + 1 because we prepend a '\0' */ + return n->on_foff - ack_off_char + 1; + } else + return 0; /* no name */ +} + +/* Convert a symbol's type and binding from ack.out to ELF. */ + +int cvinfo(struct outname* n) +{ + int bind, type; + + switch (n->on_type & S_ETC) { + case S_SCT: + type = 3; /* STT_SECTION */ + break; + case S_FIL: + case S_MOD: + type = 4; /* STT_FILE */ + break; + default: + switch (n->on_type & S_TYP) { + case S_MIN + TEXT: + type = 2; /* STT_FUNC */ + break; + case S_MIN + ROM: + case S_MIN + DATA: + case S_MIN + BSS: + case S_MIN + NUM_SEGMENTS: + type = 1; /* STT_OBJECT */ + break; + default: + type = 0; /* STT_NOTYPE */ + break; + } + break; + } + + if (n->on_type & S_EXT) + bind = 1; /* STB_GLOBAL */ + else + bind = 0; /* STB_LOCAL */ + + return (bind << 4) | type; +} + +/* Convert a symbol's section index from ack.out to ELF. */ + +int cvsect(struct outname* n) +{ + switch (n->on_type & S_TYP) { + case S_ABS: + return 0xfff1; /* SHN_ABS */ + case S_MIN + TEXT: + return N_TEXT; + case S_MIN + ROM: + return N_RODATA; + case S_MIN + DATA: + return N_DATA; + case S_MIN + BSS: + case S_MIN + NUM_SEGMENTS: + return N_BSS; + default: + return N_UNDEF; + } +} + /* Writes a byte. */ void emit8(unsigned char value) @@ -220,6 +326,210 @@ void emitphdr(unsigned long address, unsigned long filesize, fileoffset += filesize; } +/* The next few functions write parts of the symbol table. */ + +void emit_stab(void) +{ + struct outname* n; + int i; + + for (i = 0; i < outhead.oh_nname; i++) { + n = &outname[i]; + if (n->on_type & S_STB) { + emit32(cvname(n)); /* name index */ + emit8(n->on_type >> 8); /* type */ + emit8(cvsect(n)); /* section */ + emit16(n->on_desc); /* desc */ + emit32(n->on_valu); /* value */ + } + } +} + +void emit_symtab(void) +{ + struct outname* n; + int i, pass; + bool global; + + /* ELF .symtab must have local symbols before other symbols. + * We emit locals in pass 0, globals in pass 1. */ + for (pass = 0; pass < 2; pass++) { + for (i = 0; i < outhead.oh_nname; i++) { + n = &outname[i]; + + /* Don't emit .stab symbol in .symtab. */ + if (n->on_type & S_STB) + continue; + + global = (n->on_type & S_EXT); + if ((pass == 0 && !global) || + (pass == 1 && global)) { + emit32(cvname(n)); /* name index */ + emit32(n->on_valu); /* value */ + emit32(0); /* size = unknown */ + emit8(cvinfo(n)); /* info */ + emit8(0); /* other */ + emit16(cvsect(n)); /* section */ + } + } + } +} + +void emit_strtab(void) +{ + /* We prepend a '\0' because ELF uses offset 0 for symbols + * without a name. */ + emit8('\0'); + writef(stringarea, outhead.oh_nchar, 1); +} + +void emit_shstrtab(void) +{ + if (nstab) { + writef(shstrtab, sizeof(shstrtab), 1); + } else { + /* Skip .stab and .stabstr */ + int i = sh_name[N_SYMTAB]; + writef(shstrtab, sh_name[N_STAB], 1); + writef(shstrtab + i, sizeof(shstrtab) - i, 1); + } +} + +/* Writes out an ELF section header. */ + +void emit_sh(int i) +{ + uint32_t name, type, flags, addr, offset, size, link, info, + addralign, entsize; + + /* If no debugger symbols, skip .stab and .stabstr */ + if (nstab == 0 && (i == N_STAB || i == N_STABSTR)) + return; + + name = sh_name[i]; + if (nstab == 0 && i >= N_STAB) + name -= (sh_name[N_SYMTAB] - sh_name[N_STAB]); + + switch (i) { + case N_TEXT: + case N_RODATA: + case N_DATA: + case N_STAB: + type = 1; /* SHT_PROGBITS */ + break; + case N_BSS: + type = 8; /* SHT_NOBITS */ + break; + case N_SYMTAB: + type = 2; /* SHT_SYMTAB */ + break; + case N_STABSTR: + case N_STRTAB: + case N_SHSTRTAB: + type = 3; /* SHT_STRTAB */ + break; + default: + type = 0; /* SHT_NULL */ + break; + } + + switch (i) { + case N_TEXT: + flags = 4|2; /* SHF_EXECINSTR|SHF_ALLOC */ + addr = outsect[TEXT].os_base; + offset = code_offset; + size = outsect[TEXT].os_size; + addralign = outsect[TEXT].os_lign; + break; + case N_RODATA: + flags = 2; /* SHF_ALLOC */ + addr = outsect[ROM].os_base; + offset = code_offset + outsect[TEXT].os_size; + size = outsect[ROM].os_size; + addralign = outsect[ROM].os_lign; + break; + case N_DATA: + flags = 2|1; /* SHF_ALLOC|SHF_WRITE */ + addr = outsect[DATA].os_base; + offset = code_offset + outsect[TEXT].os_size + + outsect[ROM].os_size; + size = outsect[DATA].os_size; + addralign = outsect[DATA].os_lign; + break; + case N_BSS: + flags = 2|1; /* SHF_ALLOC|SHF_WRITE */ + addr = outsect[BSS].os_base; + offset = code_offset + outsect[TEXT].os_size + + outsect[ROM].os_size + outsect[DATA].os_size; + size = outsect[BSS].os_size; + addralign = outsect[BSS].os_lign; + break; + default: + flags = addr = offset = size = addralign = 0; + break; + } + + entsize = 0; + switch (i) { + case N_STAB: + offset = stab_offset; + size = STAB_SYMBOL_SIZE * nstab; + entsize = STAB_SYMBOL_SIZE; + break; + case N_SYMTAB: + offset = symtab_offset; + size = ELF_SYMBOL_SIZE * nsym; + entsize = ELF_SYMBOL_SIZE; + break; + case N_STABSTR: + case N_STRTAB: + /* .stabstr, .strtab share the string area */ + offset = strtab_offset; + /* the + 1 because we prepend a '\0' */ + size = 1 + outhead.oh_nchar; + break; + case N_SHSTRTAB: + offset = shstrtab_offset; + size = shstrtab_size; + break; + } + + /* Link .stab to .stabstr and .symtab to .strtab */ + switch (i) { + case N_STAB: + link = N_STABSTR; + break; + case N_SYMTAB: + link = N_STRTAB; + if (nstab == 0) + link -= 2; + break; + default: + link = 0; + break; + } + + switch (i) { + case N_SYMTAB: + info = nlocal; + break; + default: + info = 0; + break; + } + + emit32(name); + emit32(type); + emit32(flags); + emit32(addr); + emit32(offset); + emit32(size); + emit32(link); + emit32(info); + emit32(addralign); + emit32(entsize); +} + /* Macros from modules/src/object/obj.h */ #define Xchar(ch) ((ch) & 0377) #define uget2(c) (Xchar((c)[0]) | ((unsigned) Xchar((c)[1]) << 8)) @@ -264,6 +574,60 @@ int rsect(FILE* f, struct outsect* sect) return 1 ; } +/* + * Read the ack.out symbol table and string area. Count symbols. + * Seek back to the current file position. + */ +int rnames(FILE* f) +{ + long told; + int i; + + /* If no symbols, then do nothing successfully. */ + if (outhead.oh_nname == 0) + return 1; + + /* Seek to the symbol table. */ + told = ftell(f); + if (told == -1) + return 0; + ack_off_char = OFF_CHAR(outhead); /* for cvname() */ + if (fseek(f, OFF_NAME(outhead), SEEK_SET)) + return 0; + + /* Using calloc(a, b) to check if a * b would overflow. */ + outname = calloc(outhead.oh_nname, sizeof(outname[0])); + if (outname == NULL) + fatal("out of memory."); + for (i = 0; i < outhead.oh_nname; i++) { + char buf[SZ_NAME], *c; + if (fread(buf, SZ_NAME, 1, f) != 1) + return 0; + c = buf; + outname[i].on_foff = get4(c); c += 4; + outname[i].on_type = uget2(c); c += 2; + outname[i].on_desc = uget2(c); c += 2; + outname[i].on_valu = get4(c); + if (outname[i].on_type & S_STB) { + nstab++; + } else { + nsym++; + if (!(outname[i].on_type & S_EXT)) + nlocal++; + } + } + + stringarea = malloc(outhead.oh_nchar); + if (stringarea == NULL) + fatal("out of memory."); + if (fread(stringarea, outhead.oh_nchar, 1, f) != 1) + return 0; + + if (fseek(f, told, SEEK_SET)) + return 0; + return 1; +} + int main(int argc, char* argv[]) { /* General housecleaning and setup. */ @@ -287,7 +651,7 @@ int main(int argc, char* argv[]) break; case 'h': - fprintf(stderr, "%s: Syntax: aelflod [-a] [-b] [-h] [-l]\n\t[-m] \n", + fprintf(stderr, "%s: Syntax: aelflod [-a] [-b] [-h] [-l]\n\t[-m] [-v] \n", program); exit(0); @@ -360,6 +724,11 @@ int main(int argc, char* argv[]) } } + /* Read the symbol table, then seek back to the section data. */ + + if (!rnames(input)) + fatal("failed to read symbol table."); + /* A few checks */ if (outsect[BSS].os_flen != 0) @@ -387,8 +756,8 @@ int main(int argc, char* argv[]) /* Ensure the base address doesn't overlap the file header. */ - codeoffset = outsect[TEXT].os_base & 0x1FFF; - if (codeoffset < (ELF_HEADER_SIZE + PROGRAM_HEADER_SIZE*PROGRAM_HEADER_COUNT)) + code_offset = outsect[TEXT].os_base & 0x1FFF; + if (code_offset < (ELF_HEADER_SIZE + PROGRAM_HEADER_SIZE*PROGRAM_HEADER_COUNT)) fatal("base address too small --- overlaps ELF header"); /* Rationalise the memory sizes. */ @@ -398,6 +767,30 @@ int main(int argc, char* argv[]) outsect[DATA].os_size = outsect[BSS ].os_base - outsect[DATA].os_base; outsect[BSS ].os_size = align(outsect[BSS].os_size, outsect[BSS].os_lign); + stab_offset = code_offset + outsect[TEXT].os_size + + outsect[ROM].os_size + outsect[DATA].os_size; + + /* If we have symbols, then calculate some offsets. */ + + if (outhead.oh_nname) { + sh_count = NUM_ELF_SECTIONS; + shstrtab_nr = N_SHSTRTAB; + shstrtab_size = sizeof(shstrtab); + if (nstab == 0) { + /* Skip .stab and .stabstr */ + sh_count -= 2; + shstrtab_nr -= 2; + shstrtab_size -= + (sh_name[N_SYMTAB] - sh_name[N_STAB]); + } + + symtab_offset = stab_offset + STAB_SYMBOL_SIZE * nstab; + strtab_offset = symtab_offset + ELF_SYMBOL_SIZE * nsym; + /* the + 1 because we prepend a '\0' */ + shstrtab_offset = strtab_offset + 1 + outhead.oh_nchar; + sh_offset = shstrtab_offset + shstrtab_size; + } + /* Write out the ELF file header. */ writef(elf_le_ident_string, 4, 1); @@ -414,33 +807,29 @@ int main(int argc, char* argv[]) emit32(1); /* ELF version again */ emit32(outsect[TEXT].os_base); /* entry point */ emit32(ELF_HEADER_SIZE); /* program header offset */ - emit32(0); /* section header offset */ + emit32(sh_offset); /* section header offset */ emit32(0); /* flags */ emit16(ELF_HEADER_SIZE); /* elf header size */ emit16(PROGRAM_HEADER_SIZE); /* program header entry size */ emit16(1); /* number of program header entries */ - emit16(0x28); /* section header entry size */ - emit16(0); /* number of section header entries */ - emit16(0); /* section header string table index = SHN_UNDEF */ + emit16(SECTION_HEADER_SIZE); /* section header entry size */ + emit16(sh_count); /* number of section header entries */ + emit16(shstrtab_nr); /* section header string table index */ /* Write out a single rwx section for the entire program. */ { - unsigned long filelength = codeoffset + - outsect[TEXT].os_size + - outsect[ROM].os_size + - outsect[DATA].os_size; - - unsigned long memlength = filelength + - outsect[BSS].os_size; - - emitphdr(outsect[TEXT].os_base & ~0x1FFF, filelength, memlength, - 0, 4|2|1); + uint32_t filelength = stab_offset; + uint32_t memlength = filelength + outsect[BSS].os_size; + + emitphdr(outsect[TEXT].os_base & ~0x1FFF, + filelength, memlength, 0, 4|2|1); } /* Write padding until the code start. */ - - fseek(output, codeoffset, SEEK_SET); + + if (fseek(output, code_offset, SEEK_SET)) + fatal("output seek error"); /* Write out the actual data. */ @@ -448,6 +837,19 @@ int main(int argc, char* argv[]) emits(&outsect[ROM]); emits(&outsect[DATA]); + /* Write out the symbol table and section headers. */ + + if (outhead.oh_nname) { + int i; + if (nstab) + emit_stab(); + emit_symtab(); + emit_strtab(); + emit_shstrtab(); + for (i = 0; i < NUM_ELF_SECTIONS; i++) + emit_sh(i); + } + if (ferror(output)) fatal("output write error"); if (outputfile) @@ -459,7 +861,7 @@ int main(int argc, char* argv[]) { uint32_t ss = 0; printf(" address length\n"); - printf(" ehdr : %08"PRIx32" %08"PRIx32"\n", outsect[TEXT].os_base & ~0x1FFF, codeoffset); + printf(" ehdr : %08"PRIx32" %08"PRIx32"\n", outsect[TEXT].os_base & ~0x1FFF, code_offset); printf(" text : %08"PRIx32" %08"PRIx32"\n", outsect[TEXT].os_base, outsect[TEXT].os_size); printf(" rom : %08"PRIx32" %08"PRIx32"\n", outsect[ROM].os_base, outsect[ROM].os_size); printf(" data : %08"PRIx32" %08"PRIx32"\n", outsect[DATA].os_base, outsect[DATA].os_size); diff --git a/util/amisc/anm.1 b/util/amisc/anm.1 index 48cdff814..a76be02cd 100644 --- a/util/amisc/anm.1 +++ b/util/amisc/anm.1 @@ -1,4 +1,4 @@ -.TH ANM 1 "$Revision$" +.TH ANM 1 2017-01-18 .SH NAME anm \- print name list .SH SYNOPSIS @@ -7,7 +7,8 @@ anm [ \-gnoprus ] [ file ... ] .I Anm prints the name list (symbol table) of each ack.out(5) format object .I file -in the argument list. If an argument is an aal(1) or arch(1) archive, +in the argument list. +If an argument is an aal(1) or arch(1) archive, a listing of each object file in the archive will be produced. If no .I file @@ -18,32 +19,24 @@ are listed. Each symbol name is preceded by its value, a section indicator and a type indicator. A section indicator can be -.SM -.B U +.SB U (undefined symbol), -.SM -.B A +.SB A (absolute symbol), -.SM -.B C +.SB C (common symbol), a section number (section related symbol), or -.SM -.B - +.SB \- (other symbol). A type indicator can be -.SM -.B F +.SB F (filename), -.SM -.B M +.SB M (module name), -.SM -.B E +.SB E (external (global) symbol), or -.SM -.B - +.SB \- (local symbol). The output is sorted alphabetically. .PP @@ -69,6 +62,5 @@ Print only undefined symbols. .TP .B \-s Sort in section order. -.sh FILES .SH SEE ALSO ack.out(5) diff --git a/util/amisc/ashow.1 b/util/amisc/ashow.1 index 842c8ea35..1aaac2623 100644 --- a/util/amisc/ashow.1 +++ b/util/amisc/ashow.1 @@ -1,12 +1,12 @@ -.TH ASLOD 1 "$Revision$" +.TH ASHOW 1 2017-01-18 .SH NAME ashow \- make the contents of an ACK object file human readable .SH SYNOPSIS ashow inputfile inputfile... .SH DESCRIPTION .I ashow -dumps the contents of an ack.out file in human-readable form. It shows +dumps the contents of an ack.out file in human-readable form. +It shows details of all symbols, relocation entries, sections, and other information. - .SH "SEE ALSO" ack.out(5) diff --git a/util/amisc/ashow.c b/util/amisc/ashow.c index 498ae3980..ec85de30d 100644 --- a/util/amisc/ashow.c +++ b/util/amisc/ashow.c @@ -140,6 +140,9 @@ showrelo() case RELOPPC: printf("\tPowerPC 26-bit address\n"); break; + case RELOLIS: + printf("\tPowerPC lis instruction\n"); + break; case RELOVC4: printf("\tVideoCore IV address in 32-bit instruction\n"); break; diff --git a/util/amisc/asize.1 b/util/amisc/asize.1 index 89454dcaf..36a4d6ada 100644 --- a/util/amisc/asize.1 +++ b/util/amisc/asize.1 @@ -1,4 +1,4 @@ -.TH ASIZE 1 "$Revision$" +.TH ASIZE 1 2017-01-18 .SH NAME asize \- size of an object file .SH SYNOPSIS diff --git a/util/amisc/aslod.1 b/util/amisc/aslod.1 index a786b13e6..5a1f857a0 100644 --- a/util/amisc/aslod.1 +++ b/util/amisc/aslod.1 @@ -1,20 +1,20 @@ -.TH ASLOD 1 "$Revision$" +.TH ASLOD 1 2017-01-18 .SH NAME aslod \- ACK simple loader .SH SYNOPSIS -aslod [-h] [-v] inputfile outputfile +.B aslod +[\-h] [\-v] inputfile outputfile .SH DESCRIPTION .I aslod -converts an absolute ack.out file into a simple binary memory -dump. It is suitable for producing RAM images, executables for +converts an absolute ack.out file into a simple binary memory dump. +It is suitable for producing RAM images, executables for simple operating systems such as CP/M, DOS, etc. - +.PP The input file must contain exactly four segments: TEXT, ROM, DATA and BSS, in that order, all occupying contiguous memory. The file must have all references resolved and be linked to a fixed address. aslod will dump the segments, in order, such that the first byte of TEXT is at offset 0 in the file (regardless of where it is in memory). - .SH "SEE ALSO" ack.out(5) diff --git a/util/amisc/aslod.c b/util/amisc/aslod.c index afc8f8c3e..72fbc8ce4 100644 --- a/util/amisc/aslod.c +++ b/util/amisc/aslod.c @@ -45,12 +45,6 @@ FILE* output; /* Output stream */ #define readf(a, b, c) fread((a), (b), (int)(c), input) #define writef(a, b, c) fwrite((a), (b), (int)(c), output) -/* Output file definitions and such */ - -#define HDR_LENGTH 32 - -char hdr[HDR_LENGTH] ; - bool verbose = false; /* Segment numbers understood by aslod. */ @@ -63,14 +57,6 @@ enum { NUM_SEGMENTS }; -#define N_EXT 040 -#define N_UNDEF 00 -#define N_ABS 01 -#define N_TEXT 02 -#define N_DATA 03 -#define N_BSS 04 -#define N_FN 037 - /* Produce an error message and exit. */ void fatal(const char* s, ...) diff --git a/util/amisc/astrip.1 b/util/amisc/astrip.1 index 2f83bf1ab..1a3fa5433 100644 --- a/util/amisc/astrip.1 +++ b/util/amisc/astrip.1 @@ -1,4 +1,4 @@ -.TH ASTRIP 1 "$Revision$" +.TH ASTRIP 1 2017-01-18 .SH NAME astrip \- remove symbols and relocation information .SH SYNOPSIS @@ -11,6 +11,7 @@ ack.out(5) format object files. This is useful to save space after a program has been debugged. .SH FILES -/tmp/s? temporary file +.IP /tmp/s? 16n +temporary file .SH "SEE ALSO" ack.out(5) diff --git a/util/amisc/build.lua b/util/amisc/build.lua index d1b8a3356..22fa396cf 100644 --- a/util/amisc/build.lua +++ b/util/amisc/build.lua @@ -4,7 +4,10 @@ local function simpleprogram(name) srcs = { "./"..name..".c" }, deps = { "h+emheaders", + "modules/src/alloc+lib", + "modules/src/data+lib", "modules/src/object+lib", + "modules/src/system+lib", } } @@ -12,11 +15,12 @@ local function simpleprogram(name) name = name.."-pkg", map = { ["$(INSDIR)/bin/"..name] = "+"..name, - ["$(PLATIND)/man/man1/"..name..".1"] = "./"..name..".1", + ["$(INSDIR)/share/man/man1/"..name..".1"] = "./"..name..".1", } } end +simpleprogram("abmodules") simpleprogram("aelflod") simpleprogram("anm") simpleprogram("ashow") @@ -27,6 +31,7 @@ simpleprogram("astrip") installable { name = "pkg", map = { + "+abmodules-pkg", "+aelflod-pkg", "+anm-pkg", "+ashow-pkg", diff --git a/util/arch/aal.1 b/util/arch/aal.1 index 93b41191e..7f9af68ed 100644 --- a/util/arch/aal.1 +++ b/util/arch/aal.1 @@ -1,5 +1,4 @@ -.\" $Id$ -.TH AAL 1 "$Revision$" +.TH AAL 1 2017-01-18 .ad .SH NAME aal \- archive and library maintainer @@ -18,10 +17,10 @@ only understands archives made with .PP .I Key is one character from the set -.B qdrtx, +.BR qdrtx , optionally concatenated with one or more of -.B vlc. +.BR vlc . .I Afile is the archive file. The @@ -82,9 +81,10 @@ The create option supresses the normal message that is produced when .I afile is created. .SH FILES -/tmp/ar.* temporaries +.IP /tmp/ar.* 16 +temporaries .SH "SEE ALSO" -led(6), arch(5), +led(6), arch(5) .SH BUGS If the same file is mentioned twice in an argument list, it may be put in the archive twice. diff --git a/util/arch/build.lua b/util/arch/build.lua index 54b05f981..160b9c21f 100644 --- a/util/arch/build.lua +++ b/util/arch/build.lua @@ -17,6 +17,6 @@ installable { name = "pkg", map = { ["$(INSDIR)/bin/aal"] = "+aal", - ["$(PLATIND)/man/man1/aal.1"] = "./aal.1" + ["$(INSDIR)/share/man/man1/aal.1"] = "./aal.1" } } diff --git a/util/build/build.lua b/util/build/build.lua new file mode 100644 index 000000000..41bd0b6ad --- /dev/null +++ b/util/build/build.lua @@ -0,0 +1,8 @@ +cprogram { + name = "testrunner", + srcs = { "./testrunner.c" }, + deps = { + "modules/src/data+lib" + } +} + diff --git a/util/build/testrunner.c b/util/build/testrunner.c new file mode 100644 index 000000000..fb2add562 --- /dev/null +++ b/util/build/testrunner.c @@ -0,0 +1,117 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "diagnostics.h" + +static bool timed_out = false; +static bool child_exited = false; +static char* const* command = NULL; +static int timeout = 0; +static int pid = 0; + +static void parse_arguments(int argc, char* const argv[]) +{ + program_name = argv[0]; + for (;;) + { + int c = getopt(argc, argv, "t:"); + if (c == -1) + break; + + switch (c) + { + case 't': + timeout = atoi(optarg); + break; + + default: + fatal("syntax: testrunner -- \n"); + } + } + + command = &argv[optind]; + if (!command[0]) + fatal("you must supply a command"); + if (timeout <= 0) + fatal("timeout missing or invalid"); +} + +static void sigalrm_cb(int sigraised) +{ + timed_out = true; + if (pid) + kill(pid, SIGKILL); +} + +int main(int argc, char* const argv[]) +{ + const int READ = 0; + const int WRITE = 1; + + int fds[2]; + FILE* childin; + int wstatus; + char buffer[4096]; + char* p; + + parse_arguments(argc, argv); + + pipe(fds); + pid = fork(); + if (pid == 0) + { + /* Child */ + close(fds[READ]); + close(0); + dup2(fds[WRITE], 1); + dup2(fds[WRITE], 2); + execvp(command[0], command); + _exit(1); + } + else + { + /* Parent */ + close(fds[WRITE]); + signal(SIGALRM, sigalrm_cb); + alarm(timeout); + } + + childin = fdopen(fds[READ], "r"); + if (!childin) + fatal("cannot open pipe"); + + while (!timed_out) + { + if (!fgets(buffer, sizeof(buffer), childin)) + break; + fputs(buffer, stdout); + + p = buffer; + while (isspace(*p)) + p++; + + if (strcmp(p, "@@FINISHED\n") == 0) + break; + if (strcmp(p, "@@FINISHED\r\n") == 0) + break; + } + + /* Reached via EOF or seeing a @@FINISHED. */ + + alarm(0); + + kill(pid, SIGKILL); + waitpid(pid, &wstatus, 0); + if (timed_out) + { + fprintf(stderr, "@@TIMEDOUT\n"); + exit(1); + } + exit(WEXITSTATUS(wstatus)); +} diff --git a/util/ego/descr/build.lua b/util/ego/descr/build.lua index 034ffa3ce..e9a008cc5 100644 --- a/util/ego/descr/build.lua +++ b/util/ego/descr/build.lua @@ -22,6 +22,7 @@ end build_descr("i386") build_descr("i86") build_descr("m68020") +build_descr("powerpc") installable { name = "pkg", diff --git a/util/ego/descr/powerpc.descr b/util/ego/descr/powerpc.descr new file mode 100644 index 000000000..5138cc44b --- /dev/null +++ b/util/ego/descr/powerpc.descr @@ -0,0 +1,118 @@ +wordsize: 4 +pointersize: 4 +%%RA +general registers: 19 +address registers: 0 +floating point registers: 0 +use general as pointer: yes + +register score parameters: + local variable: + (2 cases) + pointer,general + (1 size) + default -> (3,4) + general,general + (1 size) + default -> (3,4) + address of local variable: + (2 cases) + pointer,general + (1 size) + default -> (0,0) + general,general + (1 size) + default -> (0,0) + constant: + (2 sizes) + fitbyte -> (-1,-1) + default -> (-1,-1) + double constant: + (1 size) + default -> (-1,-1) + address of global variable: + (1 size) + default -> (2,8) + address of procedure: + (1 size) + default -> (-1,-1) + +opening cost parameters: + local variable: + (2 cases) + pointer + (1 size) + default -> (3,4) + general + (1 size) + default -> (3,4) + address of local variable: + (2 cases) + pointer + (1 size) + default -> (1,4) + general + (1 size) + general -> (1,4) + constant: + (2 sizes) + fitbyte -> (1000,1000) + default -> (1000,1000) + double constant: + (1 size) + default -> (1000,1000) + address of global variable: + (1 size) + default -> (2,8) + address of procedure: + (1 size) + default -> (1000,1000) + +register save costs: + (21 cases) + 0 -> (0,0) + 1 -> (6,8) + 2 -> (12,16) + 3 -> (18,24) + 4 -> (24,32) + 5 -> (30,40) + 6 -> (36,48) + 7 -> (42,56) + 8 -> (48,64) + 9 -> (54,72) + 10 -> (60,80) + 11 -> (66,88) + 12 -> (72,96) + 13 -> (78,104) + 14 -> (84,112) + 15 -> (90,120) + 16 -> (96,128) + 17 -> (102,136) + 18 -> (108,144) + 19 -> (114,152) + 0 -> (0,0) +%%UD +access costs of global variables: + (1 size) + default -> (5,12) +access costs of local variables: + (1 size) + default -> (3,4) +%%SR +overflow harmful?: no +array bound harmful?: yes +reduce sli if shift count larger than: 0 +%%CS +#include "em_mnem.h" +first time then space: +addressing modes: op_ads op_adp op_lof op_ldf op_loi op_dch op_lpb -1 + op_ads op_adp op_lof op_ldf op_loi op_dch op_lpb -1 +cheap operations: op_cii op_ciu op_cui op_cuu op_cmi op_cmu op_cmp -1 + op_cii op_ciu op_cui op_cuu op_cmi op_cmu op_cmp -1 +lexical tresholds: 1 1 +indirection limit: 8 +do not eliminate sli if index on shiftcounts: -1 + -1 +forbidden operators: -1 -1 +%%SP +global stack pollution allowed?: yes diff --git a/util/led/ack.out.5 b/util/led/ack.out.5 index b49b0976b..c8b9fc8fa 100644 --- a/util/led/ack.out.5 +++ b/util/led/ack.out.5 @@ -1,4 +1,4 @@ -.TH "ACK.OUT" 5 "$Revision$" +.TH "ACK.OUT" 5 2017-01-18 .ad .SH NAME ack.out\ \-\ ACK-assembler and link editor output @@ -14,7 +14,7 @@ further processed on another. .ta \w'#define x'u +\w'XXXXXXXX'u +\w'XXXXXXXXXXX'u .PP In the following discussion, some structures are defined using -\fBlong\fR and \fBshort\fR as type indicators. +\fBlong\fR and \fBshort\fR as type indicators. It is assumed that the size of a short is 2 bytes (chars) and that the size of a long is 4 bytes. However, these types @@ -55,7 +55,9 @@ struct outhead { }; .fi .PP +.nf #define HF_LINK 0x0004 /* unresolved references left */ +.fi .PP The fields of this structure have the following purpose: .nr x \w'oh_magic\ \ \ 'u @@ -131,9 +133,10 @@ in tact. .br The next part of an object file contains the sections themselves. Usually, the LED program places the sections right behind one another in the -target machine, taking the -alignment requirements into account. However, the user is allowed to give -the start addresses of each section. But if the user gave a start address for +target machine, taking the alignment requirements into account. +However, the user is allowed to give +the start addresses of each section. +But if the user gave a start address for say section 2, but not for section 3, section 3 will be put right behind section 2. .PP @@ -158,12 +161,13 @@ struct outrelo { /* * relocation type bits */ -#define RELSZ 0x0fff /* relocation length */ +#define RELSZ 0x0fff /* relocation length */ #define RELO1 0x01 /* 1 byte */ #define RELO2 0x02 /* 2 bytes */ #define RELO4 0x03 /* 4 bytes */ #define RELOPPC 0x04 /* 26-bit PowerPC address */ -#define RELOVC4 0x06 /* VideoCore IV address in 32-bit insruction */ +#define RELOLIS 0x05 /* PowerPC lis */ +#define RELOVC4 0x06 /* VideoCore IV address in 32-bit insruction */ #define RELPC 0x2000 /* pc relative */ #define RELBR 0x4000 /* High order byte lowest address. */ #define RELWR 0x8000 /* High order word lowest address. */ @@ -194,13 +198,16 @@ The fields of this structure have the following purpose: Contains several flags: One of RELO1, RELO2 and RELO4 is set, indicating the size of the relocatable datum, RELPC is set when the datum is relocated pc relative, RELBR and RELWR indicate byte and word order of -the relocatable datum. RELBR and RELWR are needed here. It is not sufficient +the relocatable datum. +RELBR and RELWR are needed here. +It is not sufficient to have flags for them in the header of the object file, because some machines (NS 32016) use several of the possible combinations in their instruction encoding. .IP or_sect \nxu -Contains the section number of the referenc\fIing\fR section. This is a number -that lies between S_MIN and S_MAX. The section indicated with number S_MIN +Contains the section number of the referenc\fIing\fR section. +This is a number that lies between S_MIN and S_MAX. +The section indicated with number S_MIN is the first section in the sections-section, etc. .IP or_addr \nxu Contains the address of the relocatable datum, in the form of an @@ -209,18 +216,33 @@ offset from the base of the section indicated in the \fIor_sect\fR field. Usually contains the index of the referenced symbol in the symbol table, starting at 0. In this case, the reference is to an undefined external symbol, a common -symbol, or a section name. The relocatable datum then contains +symbol, or a section name. +The relocatable datum then contains an offset from the indicated symbol or the start of the indicated section. It may, however, also have the same value as -the \fIoh_nname\fR field of the header. In this case the relocatable datum +the \fIoh_nname\fR field of the header. +In this case the relocatable datum is an absolute number, and the datum is relocated pc relative. The relocatable datum must then be relocated with respect to the base address of its section. .PP +For RELOPPC and RELOVC4, the relocatable datum is a PowerPC or +VideoCore IV instruction. +The relocation depends on the instruction, and uses an offset encoded +in the instruction. +.PP +RELOLIS assembles a PowerPC \fBlis\fR instruction. +The relocatable datum is a 4-byte integer. +The high bit is set for ha16 or clear for hi16. +The next 5 bits are the register \fIRT\fR. +The low 26 bits are a signed offset. +The relocation replaces the datum with the PowerPC instruction +\(oq\fBlis\fR\ \fIRT\fR,\ ha16[\fIsymbol\fR\ +\ \fIoffset\fR]\(cq. +.PP .B The symbol table. .br -This table contains definitions of symbols. It is referred to by -outrelo-structures, and can be used by debuggers. +This table contains definitions of symbols. +It is referred to by outrelo-structures, and can be used by debuggers. Entries in this table have the following structure: .PP .nf @@ -250,12 +272,13 @@ struct outname { .PP The members of this structure have the following purpose: .IP on_foff \nxu -Contains the offset of the name from the beginning of the file. The name -extends from the offset to the next null byte. +Contains the offset of the name from the beginning of the file. +The name extends from the offset to the next null byte. .IP on_type \nxu The S_TYP field of this member contains the section number of the symbol. Here, this number may be S_ABS for an absolute item, or S_UND, for an -undefined item. The S_EXT flag is set in this member if the symbol is external. +undefined item. +The S_EXT flag is set in this member if the symbol is external. The S_ETC field has the following flags: S_SCT is set if the symbol represents a section name, S_COM is set if the symbol represents a common name, @@ -265,15 +288,16 @@ and S_MOD is set if the symbol refers to an assembler source file item. .IP on_desc \nxu Currently not used. .IP on_valu \nxu -Is not used if the symbol refers to an undefined item. For absolute items +Is not used if the symbol refers to an undefined item. +For absolute items it contains the value, for common names it contains the size, and for anything else it contains the offset from the beginning of the section. In a fully linked binary, the beginning of the section is added. .PP .B The string area. .br -The last part of an object file contains the name list. This is just a -sequence of null-terminated strings. +The last part of an object file contains the name list. +This is just a sequence of null-terminated strings. .PP The relocation information, the symbol table, and the name list do not have to be present, but then of course we do not have a relocatable @@ -283,7 +307,6 @@ object file. .br The following miscellaneous defines might come in handy when reading object files: -.fi .PP .nf /* diff --git a/util/led/archive.c b/util/led/archive.c index e36958d17..7e39e9fb7 100644 --- a/util/led/archive.c +++ b/util/led/archive.c @@ -6,8 +6,10 @@ static char rcsid[] = "$Id$"; #endif -#include #include +#include +#include +#include #include "arch.h" #include "out.h" #include "ranlib.h" diff --git a/util/led/const.h b/util/led/const.h index 40ad395b5..d2d27f51a 100644 --- a/util/led/const.h +++ b/util/led/const.h @@ -4,8 +4,6 @@ */ /* $Id$ */ -typedef int bool; - #define FALSE 0 #define TRUE 1 diff --git a/util/led/debug.h b/util/led/debug.h index 0e493185d..715409d25 100644 --- a/util/led/debug.h +++ b/util/led/debug.h @@ -17,3 +17,5 @@ extern int DEB; extern int Verbose; #define verbose(s, a1, a2, a3, a4) (Verbose && do_verbose(s, a1, a2, a3, a4)) + +extern void fatal(char* format, ...); diff --git a/util/led/error.c b/util/led/error.c index e7f4fc6ec..61dc7983e 100644 --- a/util/led/error.c +++ b/util/led/error.c @@ -6,9 +6,11 @@ static char rcsid[] = "$Id$"; #endif -#include -#include #include +#include +#include +#include +#include #include #include "const.h" @@ -73,7 +75,7 @@ do_verbose(char *format, ...) static void diag(char *tail, char *format, va_list ap) { - extern char *progname, *archname, *modulname; + extern char *progname, *archname, *modulname; fprintf(stderr, "%s: ", progname); if (archname && modulname) diff --git a/util/led/extract.c b/util/led/extract.c index 5878d527d..48a2f16c6 100644 --- a/util/led/extract.c +++ b/util/led/extract.c @@ -6,8 +6,10 @@ static char rcsid[] = "$Id$"; #endif -#include #include +#include +#include +#include #include "out.h" #include "const.h" #include "debug.h" diff --git a/util/led/finish.c b/util/led/finish.c index 2eace760b..439d4b364 100644 --- a/util/led/finish.c +++ b/util/led/finish.c @@ -6,6 +6,10 @@ static char rcsid[] = "$Id$"; #endif +#include +#include +#include +#include #include #include "const.h" #include "defs.h" diff --git a/util/led/led.6 b/util/led/led.6 index c89866efe..8e4b98e69 100644 --- a/util/led/led.6 +++ b/util/led/led.6 @@ -1,4 +1,4 @@ -.TH LED 6 "$Revision$" +.TH LED 6 2017-01-18 .ad .SH NAME led \- link editor @@ -78,7 +78,7 @@ The previous remarks about and .I nnnn apply. -.TP +.TP .B \-o The .I name @@ -88,7 +88,7 @@ is used as the name of the .I led output file, instead of .BR a.out . -.TP +.TP .B \-r Generate relocation information in the output file so that it can be the subject of another @@ -104,7 +104,8 @@ at load time. This flag disables the \fB\-r\fP flag. .TP .B \-n Usually, after linking, a value in the namelist represents an absolute -address. Sometimes, particularly when using the \fB\-c\fR flag, it may be +address. +Sometimes, particularly when using the \fB\-c\fR flag, it may be useful to have as value the offset with respect to the beginning of the corresponding section. The \fB\-n\fR flag enables this. .TP @@ -112,7 +113,7 @@ corresponding section. The \fB\-n\fR flag enables this. `Strip' the output, that is, remove the name table and relocation information to save space (but impair the usefulness of the debuggers). -.TP +.TP .B \-u Take the following argument as a symbol and enter it as undefined in the name table. @@ -129,9 +130,12 @@ chose to link it (which unresolved reference it resolves). This option is useful in resolving 'multiply defined' problems. .SH FILES ~em/lib.bin/em_led -a.out output file +.PD 0 +.IP a.out 24n +output file +.PD .SH "SEE ALSO" -ack(1) -arch(1) -ack.out.h(5) +ack(1), +arch(1), +ack.out.h(5), uni_ass(6) diff --git a/util/led/main.c b/util/led/main.c index b176514cb..c9a3895d2 100644 --- a/util/led/main.c +++ b/util/led/main.c @@ -12,7 +12,9 @@ static char rcsid[] = "$Id$"; #include #include -#include +#include +#include +#include #include #include "const.h" #include "debug.h" @@ -31,15 +33,16 @@ int Verbose = 0; static initializations(); static first_pass(); -static long number(); -static setlign(); -static setbase(); +static uint32_t number(const char *); +static void setlign(int, uint32_t); +static void setbase(int, uint32_t); static struct outname *makename(); static pass1(); static evaluate(); -static void norm_commons(); +static void norm_commons(); static complete_sections(); -static void change_names(); +static void change_names(); +static bool setbit(); static bool tstbit(); static second_pass(); static pass2(); @@ -126,6 +129,8 @@ first_pass(argv) register char *argp; int sectno; int h; + extern int atoi(); + extern char *strchr(); extern int hash(); extern struct outname *searchname(); @@ -166,7 +171,7 @@ first_pass(argv) case 'c': /* * Leave relocation information in the output, so that - * a next pass can see where relocation was done. The + * a next pass can see where relocation was done. The * resulting output however is no longer relocatable. */ flagword &= ~RFLAG; @@ -251,12 +256,11 @@ first_pass(argv) * else if it starts with 0, it's octal, * else it's decimal. */ -static long -number(s) - register char *s; +static uint32_t +number(const char *s) { register int digit; - register long value = 0; + register uint32_t value = 0; register int radix = 10; if (*s == '0') { @@ -291,19 +295,17 @@ number(s) * not. Only one base may be given. The same applies for alignments. */ static char basemap[MAXSECT / WIDTH]; -static long sect_base[MAXSECT]; +static uint32_t sect_base[MAXSECT]; static char lignmap[MAXSECT / WIDTH]; -static long sect_lign[MAXSECT]; +static uint32_t sect_lign[MAXSECT]; /* /* * Set the alignment of section `sectno' to `lign', if this doesn't * conflict with earlier alignment. */ -static -setlign(sectno, lign) - register int sectno; - register long lign; +static void +setlign(int sectno, uint32_t lign) { extern bool setbit(); @@ -318,10 +320,8 @@ setlign(sectno, lign) * Set the base of section `sectno' to `base', if no other base has been * given yet. */ -static -setbase(sectno, base) - register int sectno; - register long base; +static void +setbase(int sectno, uint32_t base) { extern bool setbit(); @@ -336,7 +336,7 @@ makename(string) { static struct outname namebuf; - namebuf.on_mptr = string; + namebuf.on_foff = string - core_position - mems[ALLOMODL].mem_base; namebuf.on_type = S_UND + S_EXT; namebuf.on_valu = (long)0; @@ -459,8 +459,8 @@ struct orig relorig[MAXSECT]; static complete_sections() { - register long base = 0; - register long foff; + register uint32_t base = 0; + register uint32_t foff; register struct outsect *sc; register int sectindex; diff --git a/util/led/memory.c b/util/led/memory.c index 6349c826a..df4ee99d9 100644 --- a/util/led/memory.c +++ b/util/led/memory.c @@ -22,6 +22,9 @@ static char rcsid[] = "$Id$"; */ #include +#include +#include +#include #include #include "const.h" #include "assert.h" @@ -112,7 +115,7 @@ init_core() incore = FALSE; /* In core strategy failed. */ if (sbreak(AT_LEAST) == -1) fatal("no core at all"); - + base = BASE; for (mem = mems; mem < &mems[NMEMS]; mem++) { mem->mem_base = base; @@ -198,15 +201,15 @@ compact(piece, incr, flag) gain = (mem->mem_full + incr) >> SHIFT_COUNT; if (incr < gain) incr = gain; } - + /* * First, check that moving will result in enough space */ if (flag != FREEZE) { gain = mem->mem_left; for (mem = &mems[piece-1]; mem >= &mems[0]; mem--) { - /* - * Don't give it all away! + /* + * Don't give it all away! * If this does not give us enough, bad luck */ if (flag == FORCED) @@ -224,8 +227,8 @@ compact(piece, incr, flag) } if (min == piece) for (mem = &mems[piece+1]; mem <= &mems[NMEMS - 1]; mem++) { - /* - * Don't give it all away! + /* + * Don't give it all away! * If this does not give us enough, bad luck */ if (flag == FORCED) diff --git a/util/led/output.c b/util/led/output.c index 0ee622e3a..835627631 100644 --- a/util/led/output.c +++ b/util/led/output.c @@ -6,6 +6,10 @@ static char rcsid[] = "$Id$"; #endif +#include +#include +#include +#include #include #include "const.h" #include "memory.h" @@ -60,7 +64,7 @@ generate_section_names() extern struct outsect outsect[]; extern char *core_alloc(); - size = (long)outhead.oh_nsect * sizeof(struct outname); + size = (long)outhead.oh_nsect * sizeof(struct outname); name = (struct outname *)core_alloc(ALLOGLOB, size); if (name == (struct outname *)0) return; diff --git a/util/led/read.c b/util/led/read.c index 95ec7dd6b..3ea15925c 100644 --- a/util/led/read.c +++ b/util/led/read.c @@ -6,6 +6,11 @@ static char rcsid[] = "$Id$"; #endif +#include +#include +#include +#include + int infile; /* The current input file. */ rd_fatal() diff --git a/util/led/relocate.c b/util/led/relocate.c index c72965e75..1b8960938 100644 --- a/util/led/relocate.c +++ b/util/led/relocate.c @@ -9,6 +9,7 @@ static char rcsid[] = "$Id$"; #include #include #include +#include #include #include "out.h" #include "const.h" @@ -104,6 +105,30 @@ static uint32_t get_vc4_valu(char* addr) assert(0 && "unrecognised VC4 instruction"); } +static bool is_powerpc_memory_op(uint32_t opcode) +{ + /* Tests for any PowerPC memory indirection instruction (or + * addi) where the payload is a *signed* 16-bit value. */ + switch ((opcode & 0xfc000000) >> 26) + { + case 14: /* addi */ + case 34: /* lbz */ + case 48: /* lfs */ + case 50: /* lfd */ + case 42: /* lha */ + case 40: /* lhz */ + case 32: /* lwz */ + case 38: /* stb */ + case 52: /* stfs */ + case 54: /* stfd */ + case 44: /* sth */ + case 36: /* stw */ + return true; + } + + return false; +} + /* PowerPC fixups are complex as we need to patch up to the next two * instructions in one of several different ways, depending on what the * instructions area. @@ -125,8 +150,32 @@ static uint32_t get_powerpc_valu(char* addr, uint16_t type) /* addis / ori instruction pair */ return ((opcode1 & 0xffff) << 16) | (opcode2 & 0xffff); } + else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && + is_powerpc_memory_op(opcode2)) + { + /* addis / memoryop instruction pair */ + uint16_t hi = opcode1 & 0xffff; + uint16_t lo = opcode2 & 0xffff; - assert(0 && "unrecognised PowerPC instruction"); + /* Undo the sign adjustment (see mach/powerpc/as/mach5.c). */ + + if (lo > 0x7fff) + hi--; + + return ((hi << 16) | lo); + } + + fatal("Don't know how to read from PowerPC fixup on instructions 0x%08lx+0x%08lx", + (unsigned long)opcode1, (unsigned long)opcode2); +} + +/* RELOLIS stores a signed 26-bit offset in the low bits. */ +static uint32_t get_lis_valu(char *addr, uint16_t type) +{ + uint32_t valu = read4(addr, type) & 0x03ffffff; + if (valu & 0x02000000) + valu |= 0xfc000000; /* sign extension */ + return valu; } /* @@ -144,6 +193,8 @@ static uint32_t getvalu(char* addr, uint16_t type) return read4(addr, type); case RELOPPC: return get_powerpc_valu(addr, type); + case RELOLIS: + return get_lis_valu(addr, type); case RELOVC4: return get_vc4_valu(addr); default: @@ -263,14 +314,58 @@ static void put_powerpc_valu(char* addr, uint32_t value, uint16_t type) else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && ((opcode2 & 0xfc000000) == 0x60000000)) { + /* addis / ori instruction pair */ uint16_t hi = value >> 16; uint16_t lo = value & 0xffff; write4((opcode1 & 0xffff0000) | hi, addr+0, type); write4((opcode2 & 0xffff0000) | lo, addr+4, type); } + else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && + is_powerpc_memory_op(opcode2)) + { + /* addis / memoryop instruction pair */ + uint16_t hi = value >> 16; + uint16_t lo = value & 0xffff; + + /* Apply the sign adjustment (see mach/powerpc/as/mach5.c). */ + + if (lo > 0x7fff) + hi++; + + write4((opcode1 & 0xffff0000) | hi, addr+0, type); + write4((opcode2 & 0xffff0000) | lo, addr+4, type); + } + else - assert(0 && "unrecognised PowerPC instruction"); + fatal("Don't know how to write a PowerPC fixup to instructions 0x%08lx+0x%08lx", + (unsigned long)opcode1, (unsigned long)opcode2); +} + +/* Writes a PowerPC lis instruction. */ +static void put_lis_valu(char* addr, uint32_t value, uint16_t type) +{ + uint32_t opcode, reg; + uint16_t hi, lo; + bool ha16; + + /* ha16 flag in high bit, register in next 5 bits */ + opcode = read4(addr, type); + ha16 = opcode >> 31; + reg = (opcode >> 26) & 0x1f; + + /* + * Apply the sign adjustment if the ha16 flag is set and the + * low half is a negative signed 16-bit integer. + */ + hi = value >> 16; + lo = value & 0xffff; + if (ha16 && lo > 0x7fff) + hi++; + + /* Assemble lis reg, hi == addis reg, r0, hi. */ + opcode = (15 << 26) | (reg << 21) | (0 << 16) | hi; + write4(opcode, addr, type); } /* @@ -294,6 +389,9 @@ static putvalu(uint32_t valu, char* addr, uint16_t type) case RELOPPC: put_powerpc_valu(addr, valu, type); break; + case RELOLIS: + put_lis_valu(addr, valu, type); + break; case RELOVC4: put_vc4_valu(addr, valu); break; @@ -339,7 +437,7 @@ addrelo(relo, names, valu_out) extern int hash(); extern struct outname *searchname(); extern unsigned indexof(); - extern struct outhead outhead; + extern struct outhead outhead; name = searchname(local->on_mptr, hash(local->on_mptr)); if (name == (struct outname *)0) diff --git a/util/led/save.c b/util/led/save.c index 3804413d9..952649633 100644 --- a/util/led/save.c +++ b/util/led/save.c @@ -10,8 +10,10 @@ static char rcsid[] = "$Id$"; * If everything is kept in core, we must save some things for the second pass. */ -#include #include +#include +#include +#include #include #include "arch.h" #include "out.h" diff --git a/util/led/scan.c b/util/led/scan.c index a870f8e05..1740a14de 100644 --- a/util/led/scan.c +++ b/util/led/scan.c @@ -6,8 +6,10 @@ static char rcsid[] = "$Id$"; #endif -#include #include +#include +#include +#include #ifdef SYMDBUG #include #include diff --git a/util/led/sym.c b/util/led/sym.c index 2ec47b6b7..53f0f3440 100644 --- a/util/led/sym.c +++ b/util/led/sym.c @@ -10,8 +10,10 @@ static char rcsid[] = "$Id$"; * Symbol table management. */ -#include #include +#include +#include +#include #include "out.h" #include "const.h" #include "memory.h" @@ -49,7 +51,7 @@ init_symboltable() * in the hash table is followed. If the names match, a pointer to the outname * in this element of the list is returned. When a match cannot be found, * NIL is returned. - */ + */ struct outname * searchname(string, hashval) char *string; @@ -74,7 +76,7 @@ searchname(string, hashval) debug("found %x, %x, %lx\n", name->on_type, name->on_desc, name->on_valu, 0); return name; - } + } symindex = sym->sy_next; } /* Not found. */ diff --git a/util/led/write.c b/util/led/write.c index d77ea98ef..b916949ae 100644 --- a/util/led/write.c +++ b/util/led/write.c @@ -6,8 +6,10 @@ static char rcsid[] = "$Id$"; #endif -#include #include +#include +#include +#include #include #include "out.h" #include "const.h" @@ -75,7 +77,7 @@ end_write() for (sectindex = 0; sectindex < outhead.oh_nsect; sectindex++) wrt_name(sectname(sectindex), 1); } - + wrt_emit(emit, sectindex, cnt) char *emit; int sectindex; diff --git a/util/misc/build.lua b/util/misc/build.lua index dd207bbbc..e8dfbca33 100644 --- a/util/misc/build.lua +++ b/util/misc/build.lua @@ -41,59 +41,7 @@ installable { ["$(PLATDEP)/em_encode"] = "+encode", ["$(PLATDEP)/em_decode"] = "+decode", ["$(INSDIR)/bin/esize"] = "+esize", - ["$(PLATIND)/man/man1/esize.1"] = "./esize.1", - ["$(PLATIND)/man/man6/em_decode.6"] = "./em_decode.6" + ["$(INSDIR)/share/man/man1/esize.1"] = "./esize.1", + ["$(INSDIR)/share/man/man6/em_decode.6"] = "./em_decode.6" } } - ---[[ -D := util/misc - -define build-misc-impl - $(call reset) - $(call cfile, $D/esize.c) - $(call cprogram, $(BINDIR)/esize) - $(call installto, $(INSDIR)/bin/esize) - - $(call reset) - $(eval q := $D/esize.1) - $(call installto, $(INSDIR)/share/man/man1/esize.1) - - $(call reset) - $(eval objdir := encode) - $(call cfile, $D/convert.c) - $(eval $q: $(INCDIR)/em_comp.h $(INCDIR)/em_codeEK.h) - $(call rawfile, $(LIBREAD_EMEV)) - $(call rawfile, $(LIBEMK)) - $(call rawfile, $(LIBEM_DATA)) - $(call rawfile, $(LIBALLOC)) - $(call rawfile, $(LIBPRINT)) - $(call rawfile, $(LIBSTRING)) - $(call rawfile, $(LIBSYSTEM)) - $(call cprogram, $(BINDIR)/em_encode) - $(call installto, $(PLATDEP)/em_encode) - $(eval EM_ENCODE := $o) - $(eval ACK_CORE_TOOLS += $o) - - $(call reset) - $(eval objdir := decode) - $(call cfile, $D/convert.c) - $(eval $q: $(INCDIR)/em_comp.h $(INCDIR)/em_codeEK.h) - $(call rawfile, $(LIBREAD_EMKV)) - $(call rawfile, $(LIBEME)) - $(call rawfile, $(LIBEM_DATA)) - $(call rawfile, $(LIBALLOC)) - $(call rawfile, $(LIBPRINT)) - $(call rawfile, $(LIBSTRING)) - $(call rawfile, $(LIBSYSTEM)) - $(call cprogram, $(BINDIR)/em_decode) - $(call installto, $(PLATDEP)/em_decode) - $(eval EM_DECODE := $o) - - $(call reset) - $(eval q := $D/em_decode.6) - $(call installto, $(INSDIR)/share/man/man6/em_decode.6) -endef - -$(eval $(build-misc-impl)) ---]] diff --git a/util/misc/em_decode.6 b/util/misc/em_decode.6 index 92f7a084d..a21c939eb 100644 --- a/util/misc/em_decode.6 +++ b/util/misc/em_decode.6 @@ -1,8 +1,7 @@ -.\" $Id$ -.TH EM_DECODE 6 "$Revision$" +.TH EM_DECODE 6 2017-01-18 .ad .SH NAME -em_decode,em_encode \- compact to readable EM and v.v. +em_decode, em_encode \- compact to readable EM and v.v. .SH SYNOPSIS .B ~em/lib.bin/em_decode [ inputfile [ outputfile ] ] diff --git a/util/misc/esize.1 b/util/misc/esize.1 index e62a17028..c05eb42f3 100644 --- a/util/misc/esize.1 +++ b/util/misc/esize.1 @@ -1,4 +1,4 @@ -.TH ESIZE I +.TH ESIZE 1 2017-01-18 .SH NAME esize \- print info from e.out header .SH SYNOPSIS @@ -9,7 +9,8 @@ esize \- print info from e.out header prints information from the .I e.out headers of the indicated files, including flags, word and pointer sizes, -text and data sizes, etc. All values are in decimal. +text and data sizes, etc. +All values are in decimal. .PP If no parameters are given, the header of .I e.out diff --git a/util/opt/em_opt.6 b/util/opt/em_opt.6 index bdb6587d9..267bd9c69 100644 --- a/util/opt/em_opt.6 +++ b/util/opt/em_opt.6 @@ -1,11 +1,10 @@ -.\" $Id$ -.TH EM_OPT 6 "$Revision$" +.TH EM_OPT 6 2017-01-18 .ad .SH NAME em_opt \- EM peephole optimizer .SH SYNOPSIS .B ~em/lib.bin/em_opt -[-Ln] [-m[l]] [ argument ] +[\-Ln] [\-m[l]] [ argument ] .SH DESCRIPTION Em_opt reads a compact EM-program, argument or standard input, and produces another compact EM program on standard output @@ -15,22 +14,22 @@ Some other functions are here that make this program mandatory before running a codegenerator, it may be left out when interpretation is wanted. Flags recognized are: -.IP -L +.IP \-L Make a library module. This means that the output will start with a message giving the names of all exported entities in this module. -.IP -n +.IP \-n Do not optimize. No peephole optimizations will be performed, other functions will be carried out. -.IP -m +.IP \-m Try to replace multiplies with constants by combinations of shifts and adds, -but no more than of them. Integer overflow detection is lost with this -option. -.IP -ml -Like -m, but also for long multiplies. +but no more than of them. +Integer overflow detection is lost with this option. +.IP \-ml +Like \-m, but also for long multiplies. .SH "FILES" -/tmp/emopt??????, is used when the -L flag is given only. +/tmp/emopt??????, is used when the \-L flag is given only. .SH "SEE ALSO" ack(1) .PD 0