Virtual processor Simpleton 4

Discussion of development of software for any "obsolete" computer or video game system. See the WSdev wiki and ObscureDev wiki for more information on certain platforms.
Post Reply
User avatar
aa-dav
Posts: 220
Joined: Tue Apr 14, 2020 9:45 pm
Location: Russia

Virtual processor Simpleton 4

Post by aa-dav »

Github page: https://github.com/aa-dav/SimpX#readme (including most actual documentation)
Online emulator+assembler: https://aa-dav.github.io/(select one of the 'test*.asm' files in list and click menu 'Compile and run')

Some of 8bit-guy videos including covering of project 'Gigatron TTL' inspired me to make some ISAs and virtual PC around it.
This is fourth generation of the same idea (see below).

First of all: this ISA is definitely suboptimal.
The only goal is to make instruction format as simple as possible keeping programming flexible and non-esoteric.
I know that code density could be improved, leading to something like MSP 430 as a result. So, it's not an option. :)
Last edited by aa-dav on Sun Jun 11, 2023 9:33 pm, edited 7 times in total.
User avatar
aa-dav
Posts: 220
Joined: Tue Apr 14, 2020 9:45 pm
Location: Russia

Re: Virtual processor Simpleton 4

Post by aa-dav »

Having previous version of Simpleton 3 it was easy to make quick progress in implementing Simpleton 4.
Most assembler commands have syntax:

Code: Select all

CMD R Y X
where R is destination and Y and X are operands.
If X is omitted it becomes immediate 0.

Very simple assembler implementation works. I defined input-output port which behaves like console input/output in host environment (Linux/Windows) like now.
So this program:

Code: Select all

PORT_CONSOLE    = $FFFF

		move sp $70	; Setup stack

		move r0 str0	; shortcut for addis r0 str0 0
		call str_print	; shortcut for addis [ sp ] pc 2 : addis pc str_print 0
		move r0 str0
		call str_print
		dw 0 ; STOP

str_print	movet r1 [ r0 ]
		jz .exit		; shortcut for cadd pc pc _calculated_constant_ (mix of offset and condition code)
		move [ PORT_CONSOLE ] r1	; output char to console
		addi r0 r0 1	; increment r0
		move pc str_print	; jump to the beginning of procedure
.exit		ret			; shortcut for move pc [ sp ]


str0		dw "Hello, world!" 10 0
So, it outputs 'Hello, world!" string twice as planned.
User avatar
aa-dav
Posts: 220
Joined: Tue Apr 14, 2020 9:45 pm
Location: Russia

Re: Virtual processor Simpleton 4

Post by aa-dav »

I am not experienced in schematics and hardware creation, but I hope some day I will have enough time to learn more about it and create Simpleton-based system in real hardware (FPGA).

Another thing which seems like challenge is interrupt handling.
The problem is: interrupt ignition (like in typical CPU) is a too complex thing for Simpleton base design: R = Y op X.
Simpleton cannot do CALL in single instruction, but interrupt is more complex task!

But I think it could be solved without breaking Simpleton rules.
Main instrument of solution is indirect PC reading: [ PC++ ] is used in so many places:
- reading instruction opcode
- reading immediate data (like $100)
- reading immediate indirect (like [ $100 ] (which is [ PSW ] in opcode, but it is implemented as [ PC++ ] giving address of memory cell we work with)
So... Let it be in this way: external signal of interrupt request engages special mode of [ PC++ ] indirect PC reading: it stops to read from main memory and post-increment PC. This is just bit in flags (PSW register) and if it is set - [ PC++ ] addressing mode starts to read from little internal CPU buffer of 8 or 16 words. This buffer contains program with immediate data (but it's invisible for any other reads).
It can contans program like this:

Code: Select all

addis [ sp ] pc 2 ; prepare return address, remember that direct PC reads/writes work as usual
move pc irq_handler ; point pc to irq_handler
or [ sp ] psw disable_special_mode_mask ; save flags without 'special mode' flag to stack (see below)
or psw psw disable_special_mode_mask ; This is there special [ PC++ ] mode will be shut off and program will continue from new PC
(7 words long)
That is - this internal 'special mode handler' executes CALL instruction (delayed until we exit special mode) which pushed return address to stack, points PC to interrupt handler, saves flags to stack and then disables 'special mode'. After that program continues in normal mode, but in irq handler.
So, return from interrupt will be usual code in ROM/RAM:

Code: Select all

move flags [ sp ] ; restore flags
move pc [ sp ] ; return to program interrupted (RET pseudoop is available)
I think we could do many many things with such internal 'microcode' despite Simpleton has very simple instruction format.
Note, that jumps are not possible in this internal buffer because no special program counter is visible to CPU. But it exists and is set to 0 then special mode flag is set.

So, I think interrupts activation could be implemented not so hard in Simpleton 4 without complex logic of unusual instruction code/format.
User avatar
aa-dav
Posts: 220
Joined: Tue Apr 14, 2020 9:45 pm
Location: Russia

Re: Virtual processor Simpleton 4

Post by aa-dav »

One thing I always dislike in assemblers is symbolic syntax which is verbose and unintuitive.
So, I implemented math-notation for Simpleton 3 which uses C-like expressions like in 'R0 += [ label ]'.
Simpleton4 instruction set makes it harder to implement math-notation, so I started from classic assembler as above.
But math-notation will be implemented in Simpleton 4 too.
Most of instructions could be expressed as 'R = Y op X' where 'op' is operation sign.
If X is omitted it becomes literal '0' (zero).
If 'op' is omitted it becomes '+' sign, so pseudoinstruction 'move' is not needed anymore (see below).
Next instructions fulfill this pattern (example for R=R0, Y=R1 and X=[ label ]):

Code: Select all

02 - ADDS  - r0 = r1 +s [ label ] ; add silent (doesn't update flags)
03 - ADD  - r0 = r1 +  [ label ] ; add
04 - ADC  - r0 = r1 +c [ lavel ] ; add with carry
05 - SUB  - r0 = r1 -  [ label ] ; sub
06 - SBC  - r0 = r1 -c [ label ] ; sub with carry
07 - AND  - r0 = r1 &  [ label ] ; and
08 - OR   - r0 = r1 |  [ label ] ; or
09 - XOR  - r0 = r1 ^  [ label ] ; xor
0A - CMP  - r0 = r1 ?  [ label ] ; compare (as Y - X), op updates flags and returns Y
0B - CADD - r0 = r1 +? [ label ] ; conditional add. never updates flags.
0D - RRC  - r0 = r1 >> [ label ] ; rotate Y right (cyclic) by X bits
But there are 3 opcodes (right now) which fall out of this pattern and have special syntax:

Code: Select all

00 - ADDIS - r0 <- r1 - 1         ; add Y with INPLACE immediate in XI+X SILENT (flags are not updated)
01 - ADDI  - r0 <= r1 + 3         ; add Y with INPLACE immediate in XI+X
0C - RRCI  - r0 <= r1 >> 15       ; rotate Y right (cyclic) by INPLACE immediate bits
First of all - it's 'inplace immediate' commands: addi, addis and rcci. These of them who updates flags use '<=' as sign of this special case.
The only exceptions is 'addis' which uses '<-' to signal that it's not updates flags.

Note, that 'addis a b -1' (negative inplace immediate) could be expressed in new syntax as 'a <- b + -1'. But also 'a <- b - 1' is correct (that is like 'sub' opcode). This is another reason for exclusion of addi(s) from regular '=' syntax.
Also, 'move' is as simple as: 'a <- b' which is shortcut for 'a <- b + 0'.

Note, that all pseudoops used for simplicity are still in place: 'jnz/call/ret' and so on.

So, example above could be rewritten as:

Code: Select all

PORT_CONSOLE    = $FFFF

            sp <- $70       ; Setup stack

            r0 <- str0      ; shortcut for addis r0 str0 0
            call str_print
            r0 <- str0
            call str_print
            dw 0 ; STOP

str_print   r1 <= [ r0 ]           ; testing move (addi r1 [ r0 ] 0)
            jz .exit           
            [ PORT_CONSOLE ] <- r1 ; output char to console
            r0 <- r0 + 1           ; increment r0
            pc <- str_print        ; jump to the beginning of procedure
.exit       ret                    ; shortcut for move pc [ sp ]

str0        dw "Hello, world!" 10 0
Last edited by aa-dav on Thu Mar 25, 2021 10:28 pm, edited 4 times in total.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Virtual processor Simpleton 4

Post by lidnariq »

Before long you'll be looking through the APL unicode points and thinking you want to use those for your assembly mnemonics :mrgreen:
User avatar
aa-dav
Posts: 220
Joined: Tue Apr 14, 2020 9:45 pm
Location: Russia

Re: Virtual processor Simpleton 4

Post by aa-dav »

lidnariq wrote: Sat Feb 06, 2021 9:39 pm Before long you'll be looking through the APL unicode points and thinking you want to use those for your assembly mnemonics :mrgreen:
:) Nah, I'm totally ok with this. ASCII is mandatory.
User avatar
aa-dav
Posts: 220
Joined: Tue Apr 14, 2020 9:45 pm
Location: Russia

Re: Virtual processor Simpleton 4

Post by aa-dav »

New (math-)assembler syntax is implemented and pushed to github.
Keyword 'mode' switches between modes: 'mode classic' and 'mode new'.
So, code just above should be started with 'mode new' line.
User avatar
aa-dav
Posts: 220
Joined: Tue Apr 14, 2020 9:45 pm
Location: Russia

Re: Virtual processor Simpleton 4

Post by aa-dav »

During discussion on another forum I was gifted with excellent idea!
(Many thanks to Lethargeek from https://hype.retroscene.org (russian resource)!)

In Simpleton 4 writing to indirect PC (like in 'move [ pc ] $100') is forbidden because of total meaninglessness (unlike indirect PC reading which implements 16-bit immediates).
But also 3-operand-style 'cmp' instruction acts strange ( like in 'r0 = r0 ? r1' - comparison returns first argument (Y) from ALU as result to be in touch with Simpleton architecture).

The idea is to ignore writing of result from ALU if destination (R) is [ pc ]!
ALU updates flags in operation, but result is ignored if destionation is [ pc ].
I bind keyword 'void' to indirect writing to PC in assembler and this allows to make non-destructing comparisons:

Code: Select all

sub void A B ; acts like 'cmp A B' in many other ISAs
jnz ...
or bit tests (of any kind):

Code: Select all

and void r0 $0001
jz ...
...or comparison of number with constant in range -8..+7 via one-word instruction (inplace immediate):

Code: Select all

addi void r0 -3
jz ... ; r0 is equal to 3
...or checking of i-th bit of operand via placing it in carry flag during RRCI instruction execution:

Code: Select all

rrci void r0 3 ; CF gets bit 3
jc ... ; jump if CF=1
This is truly amazing: by exploiting forbidden destination in this way we free up 'CMP' opcode and get a lot of more instructions and techniques in return! :D
Github page (code and documentation, link is in the very beginning of theme) already has these changes and it works!
User avatar
aa-dav
Posts: 220
Joined: Tue Apr 14, 2020 9:45 pm
Location: Russia

Re: Virtual processor Simpleton 4

Post by aa-dav »

Emulation of SimpX (Simpleton-based virtual old-school-PC) goes online!
Link: https://aa-dav.github.io/
To run first demo select file 'test0.asm' in the left panel and click 'Emulation->Run' menu.
It' interesting to hear about FPS (are shown in the bottom status line) with full-screen and 200/300/400% (selected in 'View') menu. To go back to full-document scale just change size of Browser window in any way (for example: minimize/maximize).

It tries to be simple as it's CPU, so video mode tries to cover bitmap-based and tile-based modes at the same time trying to be convenient for both: tile-based graphics and bitmap-based. There is single video mode there 8x8 tiles are arranged in 256x256 bitmap from left-to-right top-down manner as it's 2d bitmap and not linear tile descriptor array. There are 1024 (32x32) tiles possible so if we fill tilemap (32x32 word) with increasing numbers 0..1023 we get linear screen bitmap for linear quick screen buffer to draw.
Each tile has 4bpp 16-colors, but tile number (in word of memory (Simpleton has no bytes at all)) also stores in upper 4 bits subpalette number, so there is 16 colors in tile and 256 colors on the screen. Effective screen is 256x192 pixels wide with ability to hide rightmost 8 pixel columns to implement seamless hardware scrolling.
User avatar
aa-dav
Posts: 220
Joined: Tue Apr 14, 2020 9:45 pm
Location: Russia

Re: Virtual processor Simpleton 4

Post by aa-dav »

Some guy with nickname Total Vacuum made wolf3d-like demo for SimpX.
It's available in link https://aa-dav.github.io/
Select 'test08-wold3d.asm' in list and press menu 'Emulator->Compile and run'.
It's better to select View->Set 400% to select proper screen ratio.
Control keys of this demo A/W/D (rotation and walk forward).

If you take a better look at the source code you probably will be amazed by it's cryptic nature.
It's really effect of Forth compilator which Total Vacuum has and adapted for my platform. :D
This is how real program looks like:

Code: Select all

% UF\SIMPX\core.uf
% UF\SIMPX\stdio.uf

: rshift [ $ ` r0 <= [ sp ]` ` r1 = r0 & $8000` ` r0 = r0 & $FFFE` ` r0 <= r0 >> 1` ` [ sp ] = r0 | r1` $ ] ;

:: [ ] LocX ; :: [ ] LocY ;
:: [ ] Angle ;

:: [ ] color ;
:: [ ] x ; :: [ ] y ;

:: [ ] h ;
:: [ ] j1 ; :: [ ] j2 ;

:: [ ] i0 ; :: [ ] j0 ;
:: [ ] u0 ; :: [ ] v0 ;
:: [ ] da ; :: [ ] db ;
:: [ ] a ;  :: [ ] b ;
:: [ ] u ;  :: [ ] v ;
:: [ ] u1 ; :: [ ] v1 ;
:: [ ] a1 ; :: [ ] b1 ;
:: [ ] i ;  :: [ ] j ;
:: [ ] di ; :: [ ] dj ;
:: [ ] wall ;

:: [ 13 ] Map ; :: [ 16 ] CosTable ;

:: WIDTH 64 ; :: HEIGHT 48 ;
:: BITS 5 ; :: STEP 32 \ 1<<BITS \ ; :: MASK 31 \ STEP-1 \ ;

:: over 1 ? ;
: abs # 15 rshift # + 1 + * ;

: coz abs 8 * 64 - abs 2 * 64 - ;

: cos Angle @          CosTable + @ ;
: sin Angle @ 4 - 15 & CosTable + @ ;

:: span
   color ! x !
   HEIGHT # # # h ! [ # y @ * b1 @ < { h ! 0 } ]
   h @ - 1 rshift j1 !
   j1 @ h @ + j2 !
   j1 @ [ x @ over 0 putpixel ]
   h @ [ x @ over j1 @ + color @ putpixel ]
   j2 @ - [ x @ over j2 @ + 0x2222 putpixel ]
;

: scene
   LocX @ # BITS rshift i0 ! MASK & u0 !
   LocY @ # BITS rshift j0 ! MASK & v0 !

   sin # 3 rshift da ! cos 1 rshift + ` [ sp ] <= [ sp ] >> 13` \ 8 * \ b !
   cos # 3 rshift db ! sin 1 rshift - ` [ sp ] <= [ sp ] >> 13` \ 8 * \ a !

   WIDTH [
      a @ 0 < { 0xFFFF u0 @ 0 a @ - ~ 1 STEP u0 @ - a @ } a1 ! u ! di !
      b @ 0 < { 0xFFFF v0 @ 0 b @ - ~ 1 STEP v0 @ - b @ } b1 ! v ! dj !
      u @ # STEP - x ! b1 @ # ` [ sp ] <= [ sp ] >> 11` \ 32 * \ \ <<BITS \ u1 ! * u !
      v @ # STEP - y ! a1 @ # ` [ sp ] <= [ sp ] >> 11` \ 32 * \ \ <<BITS \ v1 ! * v !
      i0 @ i !
      j0 @ j !

      1 (
         u @ v @ < # {
            x @ STEP + x !
            v @ u @ - v !
            u1 @ u !
            i @ di @ + i !
         ~
            y @ STEP + y !
            u @ v @ - u !
            v1 @ v !
            j @ dj @ + j !
         }
         wall !
      i @ Map + @ j @ rshift 1 & )

      # wall @ { a1 @ b1 ! x @ y ! } i @ j @ + 3 & { 0x1111 ~ 0x4444 } span

      a @ da @ + a !
      b @ db @ - b !
   ]
;

:: run
   LocX @ cos 4 rshift + # x ! BITS rshift i !
   LocY @ sin 4 rshift + # y ! BITS rshift j !
   i @ Map + @ j @ rshift 1 & { x @ LocX ! y @ LocY ! scene }
;

: turn Angle @ + 15 & Angle ! scene ;

:: main
   0b000000000000000
   0b011111111111110
   0b010101010101010
   0b011111111111110
   0b011110010011110
   0b011110111011110
   0b011111101111110
   0b011110111011110
   0b011110010011110
   0b011111111111110
   0b010101010101010
   0b011111111111110
   0b000000000000000
   13 [ $ over Map + ! ]
   16 [ # # coz $ CosTable + ! ]
   4 Angle !
   40 # LocX ! LocY !
   scene
   1 (
      key # #
      'w' = { run }
      'a' = { 0xFFFF turn }
      'd' = { 1 turn }
   1 )
;

main
`@end`
Graphics output is based on the 'putpixel' word (in terms of Forth) which treats screen of my architecture for simplicity as 4x4 squares ('pixels'). So, at base level of his compiler for SimpX there are two word defined - 'putpixel' and 'key':

Code: Select all

: putpixel \ x y c \
   ` r0 <= [ sp ]`

   ` r1 = [ sp ] >> 8` ` r1 = r1 + $8000` ` r1 = r1 + [ sp ]`

                    ` [ r1 ] <- r0 `
   ` r1 = r1 + $40` ` [ r1 ] <- r0 `
   ` r1 = r1 + $40` ` [ r1 ] <- r0 `
   ` r1 = r1 + $40` ` [ r1 ] <- r0 `
;

:: key ` [ LastKey ] <- 0` ` call inputChar` ` [ sp ] <= r0` ;
That's all that is used for this demo. :)
Great job.
User avatar
dink
Posts: 157
Joined: Sun Jan 12, 2020 8:42 pm

Re: Virtual processor Simpleton 4

Post by dink »

Neat :) Had some fun with this, tonight.
Post Reply