Jump to content

apersson850

Members
  • Content Count

    1,063
  • Joined

  • Last visited

Everything posted by apersson850

  1. If we instead look at what would return something for a reasonable amount of work, there are better targets. Leave BASIC as it is. It's easy to access and can do a lot, in the extended edtions, as long as you aren't in a hurry. If you are, you can stay with BASIC and learn how to include assembly support, perhaps to the extent that you build libraries with useful, and fast, functions. Or you can go Forth, which is already there and is much faster than BASIC will ever be. If you want to stay with a more conventional language, which is still very well developed on the 99/4A, you can go to Pascal. It's faster than BASIC and comparatively easy to support with assembly. Where Forth represents a slowdown, compared to assembly, of three times, Pascal is about five-six times slower. Both are stack based. In Forth, which is much closer to the hardware, that's obvious. In Pascal, it's more an under-the-hood thing. For the p-system, there are actually two possible projects, which are reasonably doable, and beneficiary. The first is to make a modern version of the p-code card, if not as an expansion box card, but at least as a side expansion "device". Today, 60 kbytes of memory and some logic for simulating GROM access to 48 of these isn't too difficult, if you are used to making hardware projects. Making a clone implies that you don't have to rewrite it, just re-package it. There may be copyright issues, although I doubt anyone would find it worth fighting. The reason for this is of course to make the p-system available to more people, since the original p-code card is pretty rare today. The second is to implement a native code generator, NCG. Many p-systems had that from the beginning, but not the one for the TI 99/4A. However, the PME does support the opcodes NAT and NAT-INFO. As far as I've been able to determine, it should be possible to run code that's been exposed to a NCG on a 99/4A too. The purpose of the NCG is to let it process an ordinary code file, produced by the compiler, and automatically replace p-code instructions by assembly equivalents. There are quite a few p-codes, that can be replaced by one, or a few, TMS 9900 instructions. You thus get rid of the PME overhead in interpreting these p-codes, and hence speed up that particular piece of code by a factor of five or so. The more complex p-code instructions, like Call global procedure or Call external intermediate, probably also Divide real, you simply let stay put as they are. They execute so many assembly instructions when they run, that the interpreter overhead is minimal. But simple things, like load constants, integer arithmetic, fetch/store local/global variables, they are translated to the NAT p-code instruction followed by the assembly code in line. I've never used any NCG myself, but I've read about that they typically don't convert an entire program, but you tell it which procedure(s) to convert, and there you do of course select those that run many times, and thus does the brunt of the work. There's no point in converting code that handles user input, or other things that aren't time critical. The beauty of the solution is of course that you write and debug your projects in Pascal, then just make a speed improvement on the selected parts, and that improvement is fully automatic.
  2. Which means that if you really win anything on the port to the new library, speedwise, depends entirely on what kind of floating point math you are doing. Do they provide the same results? I mean, are the algorithms the same? Perhaps the standard add/subtract/multiply/divide routines, which are in assembly in the console ROM, are identical in the MDOS libarary?
  3. I remember it took me quite a while to figure out how to interface between Extended BASIC and assembly programs. I like the simplicity of doing the same thing with Pascal and assembly.
  4. I checked the thread, and no, you didn't get any other feedback. You just choose to read something else than what was written. It's good to be positive, but, as you probably have seen already, I'm also of the opinion that there are better things to spend work hours on than this project.
  5. That was interesting. Does the MDOS library use the same radix 100 format as TI does?
  6. Isn't he trying to say that the floating point math routines used by TI BASIC are also used by other languages? I presume TI Extended BASIC use them, I presume Forth use them and I know for sure that the PME (p-ssytem) does use them, for its floating point math routines.
  7. As a comparison, the more efficient TMS 9995 CPU, used in the Myarc Geneve, would do the same thing in 0.28 seconds if both workspace and code would be in external RAM. If the CPU would be allowed to have both workspace (realistic) and code (a bit less realistic, but for sure doable if needed) on chip, then it would execute the loop in 0.19 seconds. And although it's true that the result depends on the software, that's true for the application software, not for the language itself. The test loop here happens to be very adapted to the instruction set of the TMS 9900, even if that probably was just a coincidence. As can be seen in my code example above, it's very efficient. Not a lot of extra instructions moving things around. Since I knew exactly what to do, I could use the register layout in the best way, to make all operations count, without any need to move things an extra time. But realizing this is something a programmer must do. When you use machines with such low throughput, compared to today's architectures, you simply have to look for and understand what's the best thing to use. Like realizing that the Forth operator U* in this case is more efficient than the * operator. You also have to realize that using BASIC to run through 15000 loops, where you use 13 digits of precision, plus exponent, for each operation, instead of using only 16 bit integers for everything except one instruction (which still is an integer, and even an unsigned one), is the wrong approach, if you need maximum speed. So no, improving BASIC in this case isn't the right way to go. And as Rich has already explored, giving BASIC an integer data type (which still doesn't help, as it has to be a 32 bit integer as well), is far too complex to be worth it. Learning how to integrate assembly into the program you use, learn Forth, use the p-system, even make a clone peripheral so you can use the p-system without having the original p-code card (which now is approaching the same level of rarity as hen's teeth), is an effort better spent.
  8. I haven't keyed it in to run it, but this assembly code would do the same thing, if I'm not mistaken. LI R0, 15000 CLR R1 LOOP INC R1 10 MOV R1,R2 14 INCT R2 10 MPY R1,R2 52 DEC R0 10 JNE LOOP 10 PRINT R2 and R3 I've included the required clock cycles for each instruction. They assume the program is running in 16 bit wide RAM, no wait states. One loop is 106 cycles, 15000 loops then 1590000 cycles, which is equivalent to 0.53 seconds. A few more cycles would be needed to execute the start of the loop and the final print of the result, but I didn't care about them. The print procedure is more complex than the loop, but runs only once.
  9. I tried Pascal. The code which BASIC requires around 200 seconds to execute, but Forth does in 9 seconds, executes in 27.878 seconds in Pascal. But then it has the same issue as the integers in Forth: The result is limited to 16 bits, and thus incorrect. Pascal doesn't have any double precision integers. It does have long integers, though, with up to 36 digits. I've rarely used them, but they are intended for things like calculations with money, where you can't allow round off errors. Since they offer variable length (declare what you need) and prioritize precision, they seem slow as melasses. var i: integer; long, a: integer[10]; begin for i := 1 to 15000 do begin long := i; a := long+(2*long); end; writeln(a); end. That code ran in 8 minutes, 56.273 seconds. So it's obvious that the priority for long integers was precision, not speed. They are probably stored one digit per byte, and thus even less efficient than the radix 100 format used for floating point numbers in the 99/4A. But using either real (same as the floating point numbers used by BASIC) or long integers suffer from the need to not only do the math, but also the conversion from the integer loop variable to a real, or long integer, before the math can be done. This particular task simply suits Forth better. If I would have to implement this in a real Pascal program, and speed was an issue, I'd do a small assembly routine to handle this particular part of the task. I noticed in a previous post that Forth runs faster with a 32 bit result than with a 16 bit result. I presume that's because the 32 bit result is unsigned? The TMS 9900 does provide the MPY instruction, which will do an unsigned multiply of two 16 bit integers, to render a 32 bit result. But the normal * operation in Forth is probably signed, which requires a few more instructions for the TMS 9900. The TMS 9995 does have a signed multiply, but that doesn't help the 99/4A.
  10. The p-system, as it's implemented on the 99/4A, is an operating system stored on an expansion card, designed to sit in the peripheral expansion box. Or to be attached to the side of the console, if you look at the early version. To my knowledge, it has never been cloned as a piece of hardware. Running that same program in Pascal isn't too useful, since a program like this one program looptest; var i: integer; a: real; begin for i := 1 to 15000 do a := i*(2+i); next i; writeln(a); end. would run the same floating point math routines as BASIC does. Using integers give the same problem as with integers in Forth. You can't multiply 15000 by 15002 and get a result within 16 bits. UCSD Pascal has a special data type, called long integers, that could be used. I don't know how efficient that implementation is, though. But they can be 36 digits long, so they are big enough.
  11. No, when I use the TI 99/4A for programming (not too frequently nowadays), I prefer to use Pascal. It already addresses the limitations of BASIC, and then some. So I have no personal interest in improving any BASIC dialect. I just used my experience in various development to point out that I found the focus in this thread, so far, to be on the wrong thing.
  12. I don't see the point at all in working with the math routines in Extended BASIC. Or any BASIC, for that matter. They are perfect for high accuracy computations, when you need them. What BASIC could benefit from is instead integer variables, perhaps with the famous VAR1% notation. Thus you could use them for all indexing and other such stuff, where no floating point math is required. They consume less memory and the math routines would be as simple as they are in Forth. Or in Pascal, for that matter, where you already have the two data types integer and real. Talking about Pascal, the p-system is a better development environment than BASIC ever was, so the idea of making a side cart which emulates the p-code card is perhaps better to spend your time on. It's quite a bit faster than BASIC, in spite of the interpreter for the p-code. And easy to augment with assembly routines, for the most time critical parts.
  13. The probability that Extended BASIC uses the same routines for floating point math as TI BASIC does is high. Other things are most certainly coded in the 8-bit wide ROM in the Extended BASIC module, a ROM which also is bank switched, which takes even more time, when that's needed. The PME, for example, the virtual processor that runs the p-system, calls the floating point math routines in console ROM for floating point arithmetic. It does not to do math with integers, though. This is the same approach as you usually would do in an assembly only program, if you need floating point math there. There are two memory locations, in scratch pad RAM, reserved for two values. They are called FAC (Floating point ACcumulator) and ARG (ARGument). Place two values in them and call FloatADD, to get them added together and the result stored in FAC. There are several other floating point routines available too. You could write your own floating point routines too, of course. But usually it's better to stay with integers, perhaps with multiple precision, as long as you can, and only resort to floating point number when you have a compelling need. Then you should know that the floating point math performed by the TI 99/4A is as good as that on TI's calculators (perhaps it's the same routines), and they are very good. So even if you don't get top speed, you do get very good accuracy. I've posted details about the PME here before. To execute a function in p-code, for which there's a direct replacement in the vocabulary of the TMS 9900, the overhead is seven times. That is, the p-code ADD can be coded in one single machine instruction, A *SP+,*SP. But to figure out what to do, the interpreter executes seven instructions. For p-codes requiring several machine instructions to be executed, like a subprogram call, the relative overhead is less, since about the same amount of instructions are used for decoding, but more useful work is done once the decoding part is done with. Printing on the screen, on the other hand, isn't fast in the p-system. Since it emulates an 80 character wide screen, it has to keep track of both the 24 line 80 column screen memory, and which part of that it should actually show on the 24 line 40 column screen.
  14. But no fix should be needed to get correct behaviour for upper and lower case letters. It's just to avoid the Alpha lock blocking the upwards movement of the joysticks.
  15. The p-code card doesn't contain any Pascal compiler. It contains the UCSD p-system, which is an operating system, and the PME (p-machine emulator). The PME is a virtual machine, which executes p-code. The idea is similar to GPL, or Java, to pick something modern. For the p-system, there's a Pascal compiler available. Some others too, but the Pascal compiler was the only one promoted for the TI 99/4A. Turbo Pasc'99 is a simplified Pascal compiler for the TI 99/4A. The only advantage it has is that it can run without the rather rare p-code card. But the Pascal version it supports is completely useless.
  16. To be able to run as it is, the p-system requires that it can house the ROM in the address space it normally uses, i.e. >4000 to >5FFF. The part in >4000 to >4FFF is fixed. Between >5000 and >5FFF it's bank switched by CRU bit >1F80. Then it assumes it can access its GROM chips at the special GROM read address, which I've forgotten now, but it's inside the DSR space too (>5C00 maybe?), and available only when the p-code card is enabled via CRU bit >1F00. Technically, the p-system can run at other places, with other GROM read addresses, but then you need to modify all address references in the program. Doable, but rather tedious and error-prone without the source code. Since there is a code repository for assembly code in the GROM too, that has to be modified as well, or the addresses in that code will not work.
  17. That's true also without the fix. The fix takes care of the fact that the joysticks don't work in all directions if Alpha lock is down. I installed the diode almost 35 years ago, or so. It still works.
  18. The disks used by the p-code card, or rather the p-system, which is the operating system the p-code card stores in its memory, are the same as the disks used for the rest of the system. From a recording format point of view, that is. The difference is that they don't use the proprietary disk catalog system the TI 99/4A uses for most other things. Like storing BASIC programs or text files for use with the Editor/Assembler or TI Writer. The principle is similar as with most Forth systems, which also don't use the normal file system, but store data in "screens" instead. A disk used by the UCSD p-system, in a TI 99/4A, has a dummy file, called PASCAL, that covers the whole disk. It's there to make the disk occupied in the view of the standard operating system. Inside this file is the p-system's own disk catalog and files. This means that it's technically possible to copy a p-system disk with the normal Disk managers, as they will think they are copying some data file on the disk, without understanding that the pseudo file actually contains a full disk image, in a different operating system. The long in the short of this is that if you can copy a normal disk, you can also copy a p-system disk. But it takes that you have the p-system disk image in your PC from the beginning, of course, or you have nothing to copy.
  19. Unless you use the trick with ord( ), UCSD Pascal represents false by 0 and true by 1. But in systems like TI BASIC, where the operation NOT is performed by an INV on the whole 16 bit word, which is used to store the variable, you do get the characteristics that 0 is false and anything that's not false must be true. Hence false is really 0 and not(0) = 0xFFFF. Which in two's complement evaluates to -1. This also leads to the confusing fact that 4 is considered true, but not(4) is also true, as it evaluates to -5, which isn't 0. Hence it's really so that there's only one intentional value for false, and one for true. But if you evaluate a value to be true or false, and do consider all 16 bits, then you have to do something about the other 65534 possible values too. The simplest thing you can do is considering everything that's not zero to be true.
  20. Yes. But UCSD Pascal has the speciality that the logic functions will render bitwise results if you use the ord( ) function on the parameters. If you don't, only the least significant bit is considered. That's the same as if you use a standard boolean, which uses only one bit in a 16-bit word.
  21. Those TI calculators I have don't have "NOT". In UCSD Pascal, the boolean value is internally represented as 0 and 1. You can create a packed array of boolean, where you can fit 16 booleans into one word. So no sign there. However, to allow bitwise and, or and not in Pascal, UCSD Pascal has the special trick of using the ord operator. It's normally used to see what the numerical value of something is. Like in the enumerated type green, red, blue and yellow, ord(red) is 1, ord(yellow) is 3. You can do an ord(one_integer_value) and ord(another_integer_value) and get the bitwise and of the two.
  22. When I was doing a lot of programming on my TI 99/4A, I usually wrote everything that was doable in Pascal in - you get it - Pascal. There are a few things you can't access, like CRU bit etc., but most things can be done in Pascal. Then, when the program was debugged and the idea found feasible, I evaluated if there were segments of code that delayed the result too much, so that they were worth the effort of converting them to assembly language. If so, I did that, thus keeping most (hopefully) of the program in the easier-to-use Pascal and only converting the parts that really makes a difference to assembler. I've never seen the need to write programs that necessarily are only one or another language, when you can use more than one in the same application, each to its benefit. There is, for example, rarely any improvement in reading data the user is typing in by an assembly program. The user is so slow anyway, that you can do that on a higher level. But processing the data, there you may gain something from going the assembly way.
  23. I agree that the CRLP is probably the culprit. It's writing to 8000 bytes of memory. Chances are you are wiping something out there. Depends on where ADRTO is.
  24. apersson850

    apersson850

  25. DELETE was used because it was a command that could be executed without any CALL and without a file open.
×
×
  • Create New...