Jump to content

apersson850

Members
  • Content Count

    1,063
  • Joined

  • Last visited

Posts posted by apersson850


  1. On ‎8‎/‎10‎/‎2015 at 3:57 PM, Willsy said:

    Then they gave it Microsoft and said "Hey, put a BASIC on this, will you?"

    Everybody interviewed claims that this part never happened. The BASIC in the TI 99/4A is instead based on the BASIC available for the TI-990 mini computers.

    • Confused 1

  2. For the TMS 9900, 70% of the instructions require 14 clock cycles or less. Minimum is 8 cycles. If we settle for an average of 12, then that implies 0.25 MIPS for the TMS 9900. Now of course not adding any wait states, extra memory accesses for addresses etc.

    Thus it will not get any faster than this.

    Multi-bit CRU instructions, shifts and advanced math takes significantly longer time to ececute. On the other hand, 52 clock cycles for MPY, compared to the complex sequence of instructions required for a CPU like the 6502 or Z80, is still fast. A reasonable 16-bit multiplication algorithm (32 bit result), using shift and add, for the 6502 would require around ten times the number of clock cycles as the MPY instruction requires. If the frqcuency then is 1 MHz for the 6502, vs. 3 MHz for the TMS 9900, we're looking at 30 times longer to do such a multiplication.

    • Like 1

  3. Since I was interested in hardware too, when I was using my TI 99/4A a lot, I implemented the all 16-bit RAM in my console. Pascal runs about 10% faster when all RAM is 16-bit wide in the machine. The main increase probably comes from things like that parts of the p-system code is loaded into 8 K RAM expansion. The 80-column screen memory is also there. Thus, some p-system runtime is spent in this memory. The inner parts of the PME are transferred to the internal RAM PAD, so they are 16-bit already. The major part of the interpreter is on the p-code card, which is 8-bit access reagardless of the RAM. User's code is running from VDP RAM, space permitting.

    • Like 2

  4. P-code can run from any memory. The PME (p-machine emulator) is written in such a way, that it will do the same thing to the code, regardless of where it is. There's a flag to keep track of which kind of memory the current code is executing from, so it can see if it needs to do any special action, when the program is calling procedures that may be in a different type of memory.

    Thus the p-system has two code pools for the user, in VDP RAM and CPU RAM (24 K expansion), as well as in GROM on the p-code card for the system itself.

    • Like 1

  5. 1 hour ago, HOME AUTOMATION said:


    You just made a new friend. Thanks for taking the time!:cool:

           AORG >7D00
           DEF REMOTE   
    REMOTE CLR  R0
           CLR  R12
           LI   R1,>3FFA	A lot of bytes to clear
           LI   R6,>B000
    NEXT   MOV  R0,*R6+		Clear a word at a time
           DEC  R1			But count bytes, so we clear >B000 - >2FF4. Should be DECT
           JNE  NEXT
           LI   R6,>B000
    WAIT   TB   17			Wait as long as bit is zero
           JEQ  WAIT
    TEST   CLR  R5			Now start measuring
    CHECK0 INC  R5
           TB   17
           JEQ  CHECK0		Count as long as it's zero, but we know already it's not, or we wouldn't be here
           MOV  R5,*R6+
           CLR  R5
    CHECK1 INC  R5			So we end up here immediately. Thus this part could come first, CHECK1 before CHECK0
           TB   17
           JNE  CHECK1
           MOV  R5,*R6+
           CI   R6,>B0FF	Much smaller than the buffer that's cleared
           JLT  TEST
           RT
           END 

     

    You're welcome. I added some comments to your code.


  6. Well, plug in Editor/Assembler, or even better, Mini Memory, and you have that. It's not the bare console, no, but I think many of these were sold to people plugging in Invaders and Parsec, and never brought it any longer than that.

    Mini Memory gave you something to work with, but otherwise there wasn't too much that was interesting to the skilled hobbyists inside the machine, as long as it had no memory expansion.

    Just making it like my modified console, with 64 K 16-bit contiguous RAM, in additon to the 16 K video RAM, makes it a whole different beast. It's a concept similar to the Commodore 64, which also had 64 K RAM, but not access to all of it when the machine was running "normally". But you could page in RAM all over, under software control, just like my console allows you to.


  7. Yes, the mini computer TI 990/9 was the original LSI implementation of the CPU, which became integrated into a chip as the TMS 9900. The TMS 9900, in turn, was used to run the TI 990/4 and TI 990/5 mini computers. Unlike its bigger brothers (e.g. the TI 990/10A), these models were usually limited to max 64 K memory. Hence the width of the address bus.

     

    Those wondering why TI selected model names like 99/4, 99/4A, 99/8 etc. have food for thought, when looking at the mini computer serie's names.


  8. On ‎11‎/‎10‎/‎2019 at 3:04 PM, HOME AUTOMATION said:

    Unfortunately, I have never used a TI RAMDISK.

    I imagine their main/sole purpose is to speed-up file processing?

    That was the main issue for me. To be able to compile a quite comprehensive version of Pascal within the small memory of the TI 99/4A, the UCSD Pascal compiler is heavily segmented. This means the drives are spinning constantly during compile time, to reload different parts of the program during operation, in addition to reading the source code and writing the object code.

    By placing the SYSTEM.COMPILER file on a RAMdisk, compile time is reduced to half, even if both the source and the object code files are on physical disks.

    • Thanks 1

  9. Thank you. I don't have any emulator installed on this computer.

    At least this implies that assuming the user has some programming skill, in the actual language (Forth or BASIC, in this case), then the approaches to use this principle in Forth, and using the method of entering a code line in BASIC, are conceptually equal.

    Thus a function plotter could use the plot environment that works best, and allow function input by programming it.

     

    It's not as fool proof as having the user enter a function as a text, parse and generate code for it (evaulate it, that is), but a lot easier to do. Based on this concept study we can say that a solution is in place. Acutally implementing it isn't important, since nobody will use this program anyway.

    • Like 1

  10. 7 hours ago, TheBF said:

    Yes as Lee mentioned the word EXECUTE and ANS Forth has the word DEFER which is like Forward in PASCAL

    Forth's word space is defined as Hyper-static.  You can define a routine called X and use it in subsequent code and then define something else called X and the old X will not be affected.  This is because lookup of labels starts with the last label defined so the newest X is found first.  So the short answer is yes, but I suspect that's not what you were looking for.

    Yes, I know you can re-use the same name, but that it doesn't really re-define the word in the contexts where it has already been used.

    So you can't define FX, define a plotter that uses FX and finally make new definitions of FX. The new definitions will replace the old, for words written now, but will not re-define FX for the plotter package. It will still see the old FX.

    Now I'm not sure exactly how DEFER works. Would this code do the same thing as the example you posted?

     \ F(X)=COS(3X) + 3X^2  in Forth
    
     INCLUDE DSK1.TOOLS
     INCLUDE DSK1.TRIG
     INCLUDE DSK1.DEFER
    
    DECIMAL 
    
     : ^2    DUP * ;
    
     DEFER F(X)
    
     : COS(3X) ( n -- n') 3 * COS ;
     : 3X^2    ( n -- n') ^2  3 * ;
    
     : TEST  ( n -- ) 0 ?DO  I F(X)  .  LOOP ;
    
     : FUNCTION1 ( n -- n') DUP COS(3X)  SWAP 3X^2  +  ;
     
     ' FUNCTION1 IS F(X)

    If you now use TEST, would you get the same result as in your example? Note that I've changed the order of things.

    If it does give the same result, then you've accomplished what I was looking for. You can expect the user to re-define F(X) and again use the plotter. This is equivalent to asking the user to key in a BASIC program line defining the function, but perhaps easier to accept in Forth, since you go back and forth between defining and executing words all the time there. In BASIC, there more of a context switch, as you use RUN to start executing, and that's clearly distinguished from immediate mode. In Pascal even more so, as there is no "immediate mode", and you need to run the compiler between creating and executing a new program.

     : FUNCTION2 ( n -- n') DUP COS(3X)  SWAP 3X^2  -  ;
     
     ' FUNCTION2 IS F(X)

    After this, then running TEST would evaluate this function instead. But I'm not sure that's what you get?


  11. Nobody would ever have used it today. Back in the 80's, yes. But today you use Excel or Matlab or stuff like that, depending on how complex the task is.

    So the task has to be fun, because it's just for fun it would be done.

     

    If you're going to start more threads like this one, then next time, I hope you learned from this attempt that you need to participate, work and learn yourself too. Otherwise you'll not encourage people to do things.

    • Like 1

  12. You don't have to worry about the slots, if you make your own cable. Ribbon cables can easily be made at home. Push the connectors together in a vice.

    Since you don't have any tab for the slot, you have to figure out how to orient them properly. But since one side of the edge connectors are all ground connections, that's not difficult to find out.


  13. 2 hours ago, Tursi said:

    (Although, the suggestion to just tell the user to enter it as a line of code and then run the program was pretty brilliant!)

    I thought it was the only realistic one, in this context. Didn't render any pizza, though.

    No, the task isn't too difficult for this community. As I've written some compilers, I know exactly how to do a recursive descent parser, for example. Including the code generation. But it's ridiculous to do in BASIC, when there are other options. So for BASIC, that suggestion I made works best.

     

    Other languages are available here, but to spend the effort to create a good program nobody will ever use, that doesn't make sense. All the less when it became obvious that you, Sid1968, had no interest whatsoever in learning anything yourself.

    Doing this because it has to be done is like work. This is a hobby. Here we learn together and create for fun.

    • Haha 2

  14. 1 hour ago, adamantyr said:

    The byte versions only work on the first/high byte, you have to use shifts or a swap byte opcode to access the other byte.

    This is not generally true.

    Byte operations like Add byte can use the addresses 123 and 345, in an instruction like AB @123,@345, and actually add the two odd-addressed bytes together, and store the result at 345. So odd-byte addressing is possible.

    However, when using registers (those that aren't, but pretend to be), in an instruction like AB R2,R4, you'll add the most significant byte of R2 with the most significant byte of R4, and store the result "to the left" in R4. If we assume the context that LWPI >1000 which defines the virtual R0 to be at >1000 in memory, preceeded the instruction

    AB R2,R4

    then this is completely equivalent to

    AB @>1004,@>1008

    The only difference is that the register only instruction requires one word, the other three. Since the first is shorter and has fewer memory accesses, it's also faster. This means that if you want to add the two least significant bytes of R2 and R4, you can use

    AB @>1005,@>1009

     

    The register file in memory makes it easy to use a separate register set momentarily, by LWPI NewWP, do whatever, then LWPI OldWP and you continue with your old values in the registers.

    The 9900 doesn't have a predefined stack register. Return from subroutines called by BL @Sub are returned from by executing B *R11. The return address is stored in R11, so by branching indirectly to that, you return to after your Branch and Link instruction. As a consequence, you can't call another subroutine from the first, unless you take care to save the return address on the first level yourself. Either you implement a stack, or save it in some handy location.

    But you can do a more elaborate BLWP @SepWSSub, to call a subroutine with a separate workspace. The Branch and Link with Workspace Pointer branches via a vector. This vector consists of two words. The address of the new workspace followed by the address of the code to run.

    In the new workspace, the BLWP instruction will automatically store the old WP in R13, the return address (old PC) in R14 and the status register, as it was prior to making the call, in R15. Hence this will give you a subroutine that has its own workspace, but can acess data in the caller's registers via R13, or data stored after the call instruction via R14. To access the caller's R5, and store this in the subroutine's R5, you'd execute

    MOV @10(R13),R5

    since the caller's R5 is ten bytes down in his workspace.

    To fetch in-line data after the call to your R6, you'd use

    MOV *R14+,R6

    This will move a word located right after the BLWP instruction to R6, and also increment R14 by two, so that it points to the actual code following the call instruction.

     

    When an interrupt is signalled, an implicit BLWP, via a vector in a pre-defined address in memory, occurs. This means that without explicitly saving anything on a stack, the interrupt starts running with a fresh set of registers, as well as with the previous status word handy, so you can return to the previously executing code and restore the context you had completely. A return is done with the RTWP instruction in both cases. RTWP uses the data in R13, R14 and R15 to restore the registers WP, PC and ST in the CPU.

     

    As explained above, the CRU is Texas Instruments version of I/O addressing. You install hardware, wired to look at the CRU command signal and decode the address given, so that you can set or read a bit from this hardware. The hardware can be anything: Latches, LSI chips with pre-defined functions, like UART, general timer/IO-chip, floppy disc controllers etc. Since it's bit-serial, you can easily define hardware ports of odd sizes. Two eight-bit latches can make three ports, five, seven and four bits wide. Many microprocessors would require three eight-bit latches to implement that efficiently, where three, one and four bits were unused.

     

    The 9900 concept is more about flexibility than utmost speed. Many instructions allow a general address, which can be either directly to a register, indirectly via a register, indirect with auto-increment, indexed or symbolic. There are no restrictions on which of these you use in that case.

    • Like 1
×
×
  • Create New...