Close
0%
0%

Katherine Peeters

I'm an open source nerd and I'm messing around with making a SUBLEQ computer from 74XX components.

Ottawa
Send a private message
Similar accounts worth following
katherine-peeters

This user joined on 05/12/2021.

View all

Share this profile

Share

Bits

agp.cooper wrote 07/14/2021 at 03:00 point

Hi Katherine,

16 bit is 64kb, assuming standard SubLEq. Yeah okay, I am over the top with my statement.

Still SubLEq is incredibly inefficient (i.e. super low code density).

Here are my results:

* 12 lines of high level language coverts to
* 74 lines of OpCodes (95 words), which converts to
* 3126 lines of Subleq including comments (5530 words).

This resulted in very slow execution.

Here is the code (in PL/0):

  begin

      A=4;
      B=1;
      if A<B then
            write A*10<b;
      else begin
           write 1<B*10;
           write B*10, (a+b)*-5;
      end
      C=-1;
      write C;
  end

Regards Alan

  Are you sure? yes | no

Katherine Peeters wrote 07/14/2021 at 03:12 point

16 bit is 65,536 addresses, which is indeed 64KiB for byte addressable memory, but my design uses word addressable memory (two bytes per address), thus 128KiB.

Those results are interesting, indeed shows extremely poor code density; did you write the SUBLEQ program by hand, or was it generated by a compiler? I'm wondering if maybe the compiler was responsible for the low performance; I'd bargain that program could be written in 100 instructions or less.

  Are you sure? yes | no

agp.cooper wrote 07/14/2021 at 05:56 point

About 4 years ago (so my memory is a bit faded) I wrote a PL/0 compiler (which produces pcode) . Then I wrote a pcode assembler that exports SubLEq. And then a SubLEq interpreter.

Well that is a challenge! 100 instructions!

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

When you get into SubLEq you will need to set up a "system", which contains useful variables and constants, and code for indirect move (which using self modifying code, unless you opt for SubLEq+). In my case that used 210 bytes (70 instructions).

I can post my system later if you like.

Here is the PCode for the 12 line of code above:

Simple OpCode:
    0: movAxImm     4
    2: movVarAx 49152
    4: movAxImm     1
    6: movVarAx 49153
    8: movAxVar 49152
   10: pushAx       0
   11: movAxVar 49153
   13: movBxAx      0
   14: popAx        0
   15: cmpBx        0
   16: setLT        0
   17: orAxAx       0
   18: jz          38
   20: movAxVar 49152
   22: pushAx       0
   23: movAxImm    10
   25: popBx        0
   26: mulBx        0
   27: pushAx       0
   28: movAxVar 49153
   30: movBxAx      0
   31: popAx        0
   32: cmpBx        0
   33: setLT        0
   34: wrtAx        0
   35: wrtLn        0
   36: jmp         81
   38: movAxImm     1
   40: pushAx       0
   41: movAxVar 49153
   43: pushAx       0
   44: movAxImm    10
   46: popBx        0
   47: mulBx        0
   48: movBxAx      0
   49: popAx        0
   50: cmpBx        0
   51: setLT        0
   52: wrtAx        0
   53: wrtLn        0
   54: movAxVar 49153
   56: pushAx       0
   57: movAxImm    10
   59: popBx        0
   60: mulBx        0
   61: wrtAx        0
   62: movAxVar 49152
   64: pushAx       0
   65: movAxVar 49153
   67: popBx        0
   68: addBx        0
   69: pushAx       0
   70: xorAxAx      0
   71: pushAx       0
   72: movAxImm     5
   74: movBxAx      0
   75: popAx        0
   76: subBx        0
   77: popBx        0
   78: mulBx        0
   79: wrtAx        0
   80: wrtLn        0
   81: xorAxAx      0
   82: pushAx       0
   83: movAxImm     1
   85: movBxAx      0
   86: popAx        0
   87: subBx        0
   88: movVarAx 49154
   90: movAxVar 49154
   92: wrtAx        0
   93: wrtLn        0
   94: halt         0

Then I substituted subleq for each PCode.

I acknowledge I did not use a library, the code was duplicated each time.

Here is the SubLEq code for PCode 26: above:

; imul Ax = Ax * Bx
    ; jump BEGINf
    Z    Z    BEGINf
; store immediate value .sgn 1
.sgn    1
; store immediate value .res 0
.res    0
; store immediate value .word 1
.word    1
; Set label BEGIN:
BEGIN:
    ; jgez Test: Ax Jump: ENDIFf
    T    T    ?
    T    Ax    L1f
    T    T    ENDIFf
L1:    Ax    T    L2f
    T    T    L3f
L2:    P    T    ENDIFf
    T    T    L3f    L3:
    ; Ax = chs Ax
    T    T    ?
    Ax    T    ?
    T    Z    ?
    Ax    Ax    ?
    Z    Ax    ?
    Z    Z    ?
    ; sgnb = chs sgnb
    T    T    ?
    sgnb    T    ?
    T    Z    ?
    sgnb    sgnb    ?
    Z    sgnb    ?
    Z    Z    ?
; Set label ENDIF:
ENDIF:
    ; jgez Test: Bx Jump: ENDIFf
    T    T    ?
    T    Bx    L1f
    T    T    ENDIFf
L1:    Bx    T    L2f
    T    T    L3f
L2:    P    T    ENDIFf
    T    T    L3f    L3:
    ; Bx = chs Bx
    T    T    ?
    Bx    T    ?
    T    Z    ?
    Bx    Bx    ?
    Z    Bx    ?
    Z    Z    ?
    ; sgnb = chs sgnb
    T    T    ?
    sgnb    T    ?
    T    Z    ?
    sgnb    sgnb    ?
    Z    sgnb    ?
    Z    Z    ?
; Set label ENDIF:
ENDIF:
; Set label LOOP:
LOOP:
    ; resb = shl resb
    T    T    ?
    resb    T    ?
    T    resb    ?
    ; jgez Test: resb Jump: ENDIFf
    T    T    ?
    T    resb    L1f
    T    T    ENDIFf
L1:    resb    T    L2f
    T    T    L3f
L2:    P    T    ENDIFf
    T    T    L3f    L3:
    ; copy resb = _MIN
    T    T    ?
    resb    resb    ?
    _MIN    T    ?
    T    resb    ?
    ; jump ERRORf
    Z    Z    ERRORf
; Set label ENDIF:
ENDIF:
    ; Ax = shl Ax
    T    T    ?
    Ax    T    ?
    T    Ax    ?
    ; jgez Test: Ax Jump: ENDIFf
    T    T    ?
    T    Ax    L1f
    T    T    ENDIFf
L1:    Ax    T    L2f
    T    T    L3f
L2:    P    T    ENDIFf
    T    T    L3f    L3:
    ; sub Ax = Ax - _MIN
    _MIN    Ax    ?
    ; add resb = resb + Bx
    T    T    ?
    Bx    T    ?
    T    resb    ?
    ; jgez Test: resb Jump: ENDIFf
    T    T    ?
    T    resb    L1f
    T    T    ENDIFf
L1:    resb    T    L2f
    T    T    L3f
L2:    P    T    ENDIFf
    T    T    L3f    L3:
    ; copy resb = _MIN
    T    T    ?
    resb    resb    ?
    _MIN    T    ?
    T    resb    ?
    ; jump ERRORf
    Z    Z    ERRORf
; Set label ENDIF:
ENDIF:
    ; wordb = shl wordb
    T    T    ?
    wordb    T    ?
    T    wordb    ?
    ; wordb = inc wordb
    N    wordb    ?
    ; jgtz Test: wordb Jump: LOOPb
    T    T    ?
    T    wordb    L1f
    T    T    LOOPb
L1:    wordb    T    L2f
    T    T    L3f
L2:    P    T    L3f
    T    T    L3f    L3:
    ; jgez Test: sgnb Jump: ENDIFf
    T    T    ?
    T    sgnb    L1f
    T    T    ENDIFf
L1:    sgnb    T    L2f
    T    T    L3f
L2:    P    T    ENDIFf
    T    T    L3f    L3:
    ; resb = chs resb
    T    T    ?
    resb    T    ?
    T    Z    ?
    resb    resb    ?
    Z    resb    ?
    Z    Z    ?
; Set label ENDIF:
ENDIF:
; Set label ERROR:
ERROR:
    ; copy Ax = resb
    T    T    ?
    Ax    Ax    ?
    resb    T    ?
    T    Ax    ?
; Set label END:
END:

I count 111 lines of actual code.

I am not trying to put you off SubLeq, just that the language is horrible.

I am happy to pass on my subleq macros (which you will need at some point).

Regards AlanX



  Are you sure? yes | no

agp.cooper wrote 07/13/2021 at 01:42 point

Hi Katherine, thanks for the follow.

I see that you are looking at a SubLEQ CPU as well.

I have  TinaTI model for my attempt that may be useful to you. TinaTI can be used to test your CPU design, but it is far from ideal.

Anyway, my finding was that a 16 bit SubLEQ was not big enough to create a stand alone programmable  demonstration computer!

SubLEQ is also the most horrible language to program in.

PM me if you want to know more about my project. 

Anyway best of luck with your project.

Regards AlanX

  Are you sure? yes | no

Katherine Peeters wrote 07/13/2021 at 02:24 point

Thanks! I'm curious as to how 16 bits might not be enough; using word addressable memory, that's 128KiB, or ~44,000 instructions, which seems like plenty to me!

  Are you sure? yes | no

Become cool instantly

Create your Hackaday.io profile like Katherine Peeters and many others