diff --git a/README.md b/README.md index 8a41367..c43dc8d 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ evaluxn(u, u->vframe); /* Each frame ### Define - `@label`, assign the current address to a label. +- `$label`, assign the current address to a local label. - `;variable 2`, assign an address to a label automatically. - `:const 1a2b`, assign an address to a label manually. - `¯o { x 2 y 2 }`, define a macro named `macro`. @@ -75,16 +76,16 @@ BRK @print-label ( text ) - NOP - ( send ) DUP2 LDR =CNSL.char - ( incr ) #0001 ADD2 - ( loop ) DUP2 LDR #00 NEQ ^print-label MUL JMPS + $loop NOP + ( send ) DUP2 LDR =CNSL.char + ( incr ) #0001 ADD2 + ( loop ) DUP2 LDR #00 NEQ ^$loop MUL JMPS POP2 -RTS +RTS -@text1 [ Hello 20 World 0a00 ] ( text with linebreak and null bytes ) -@text2 [ Welcome 20 to 20 UxnVM 0a00 ] +@text1 [ Welcome 20 to 20 UxnVM 0a00 ] +@text2 [ Hello 20 World 0a00 ] |c000 @FRAME |d000 @ERROR diff --git a/assembler.c b/assembler.c index a97393d..989d486 100644 --- a/assembler.c +++ b/assembler.c @@ -167,6 +167,15 @@ findopcode(char *s) return 0; } +char * +sublabel(char *src, char *scope, char *name) +{ + scpy(scope, src, 64); + scpy("-", src + slen(src), 64); + scpy(name, src + slen(src), 64); + return src; +} + #pragma mark - Parser int @@ -274,7 +283,7 @@ pass1(FILE *f) { int ccmnt = 0, cbits = 0; Uint16 addr = 0; - char w[64]; + char w[64], scope[64], subw[64]; printf("Pass 1\n"); while(fscanf(f, "%s", w) == 1) { if(skipblock(w, &ccmnt, '(', ')')) continue; @@ -288,6 +297,10 @@ pass1(FILE *f) } else if(w[0] == '@') { if(!makelabel(w + 1, addr, 0, NULL)) return error("Pass1 failed", w); + scpy(w + 1, scope, 64); + } else if(w[0] == '$') { + if(!makelabel(sublabel(subw, scope, w + 1), addr, 0, NULL)) + return error("Pass1 failed", w); } else if(w[0] == ';') { if(!makevariable(w + 1, &addr, f)) return error("Pass1 failed", w); @@ -308,8 +321,6 @@ pass1(FILE *f) break; case '=': addr += 4; break; /* STR helper (lit addr-hb addr-lb str) */ case '~': addr += 4; break; /* LDR helper (lit addr-hb addr-lb ldr) */ - case '$': addr += 4; break; /* JSR helper (lit addr-hb addr-lb jsr) */ - case '/': addr += 4; break; /* JMP helper (lit addr-hb addr-lb jmp) */ case ',': addr += 3; break; case '.': addr += 2; break; case '^': addr += 2; break; /* Relative jump: lit addr-offset */ @@ -328,13 +339,21 @@ int pass2(FILE *f) { int ccmnt = 0, cbits = 0, cmacro = 0; - char w[64]; + char w[64], scope[64], subw[64]; printf("Pass 2\n"); while(fscanf(f, "%s", w) == 1) { Uint8 op = 0; Label *l; - if(w[0] == '@') continue; if(w[0] == '&') continue; + if(w[0] == '$') continue; + if(w[0] == '@') { + scpy(w + 1, scope, 64); + continue; + } + if(w[1] == '$') { + sublabel(subw, scope, w + 2); + scpy(subw, w + 1, 64); + } if(skipblock(w, &ccmnt, '(', ')')) continue; if(skipblock(w, &cmacro, '{', '}')) continue; /* clang-format off */ @@ -357,8 +376,6 @@ pass2(FILE *f) else if(w[0] == ',' && (l = findlabel(w + 1))) { pushshort(findlabeladdr(w + 1), 1); l->refs++; } else if(w[0] == '=' && (l = findlabel(w + 1)) && l->len){ pushshort(findlabeladdr(w + 1), 1); pushbyte(findopcode(findlabellen(w + 1) == 2 ? "STR2" : "STR"), 0); l->refs++;} else if(w[0] == '~' && (l = findlabel(w + 1)) && l->len){ pushshort(findlabeladdr(w + 1), 1); pushbyte(findopcode(findlabellen(w + 1) == 2 ? "LDR2" : "LDR"), 0); l->refs++;} - else if(w[0] == '/' && (l = findlabel(w + 1))){ pushshort(findlabeladdr(w + 1), 1); pushbyte(findopcode("JMP2"), 0); l->refs++;} - else if(w[0] == '$' && (l = findlabel(w + 1))){ pushshort(findlabeladdr(w + 1), 1); pushbyte(findopcode("JSR2"), 0); l->refs++;} else if(w[0] == '#' && sihx(w + 1) && slen(w + 1) == 2) pushbyte(shex(w + 1), 1); else if(w[0] == '#' && sihx(w + 1) && slen(w + 1) == 4) pushshort(shex(w + 1), 1); else if(w[0] == '+' && sihx(w + 1) && slen(w + 1) == 2) pushbyte((Sint8)shex(w + 1), 1); diff --git a/etc/usm.sublime-syntax b/etc/usm.sublime-syntax index 0166c26..740cc04 100644 --- a/etc/usm.sublime-syntax +++ b/etc/usm.sublime-syntax @@ -30,6 +30,9 @@ contexts: - match: '\&(\S+)\s?' scope: string.control pop: true + - match: '\$(\S+)\s?' + scope: string.control + pop: true # Special diff --git a/projects/examples/dev.console.usm b/projects/examples/dev.console.usm index 3fbf57f..0578714 100644 --- a/projects/examples/dev.console.usm +++ b/projects/examples/dev.console.usm @@ -4,8 +4,8 @@ |0100 @RESET - ,text1 $print-label - ,text2 $print-label + ,text1 ,print-label JSR2 + ,text2 ,print-label JSR2 #ab =CNSL.byte #cdef =CNSL.short @@ -13,16 +13,14 @@ BRK @print-label ( text ) - @print-label-loop NOP + $loop NOP ( send ) DUP2 LDR =CNSL.char ( incr ) #0001 ADD2 - ( loop ) DUP2 LDR #00 NEQ ^print-label-loop MUL JMPS + ( loop ) DUP2 LDR #00 NEQ ^$loop MUL JMPS POP2 RTS -( store text in memory ) - @text1 [ Welcome 20 to 20 UxnVM 0a00 ] @text2 [ Hello 20 World 0a00 ] diff --git a/projects/examples/dev.key.usm b/projects/examples/dev.keys.usm similarity index 92% rename from projects/examples/dev.key.usm rename to projects/examples/dev.keys.usm index 3ff1dcc..3a91078 100644 --- a/projects/examples/dev.key.usm +++ b/projects/examples/dev.keys.usm @@ -65,45 +65,45 @@ RTS =dev/sprite.addr =color =rect.y2 =rect.x2 DUP2 =dev/sprite.y =rect.y1 DUP2 =dev/sprite.x =rect.x1 - @tile-rect-ver + $ver ~rect.x1 =dev/sprite.x - @tile-rect-hor + $hor ( draw ) ~color =dev/sprite.color ( incr ) ~dev/sprite.x #0008 ADD2 =dev/sprite.x - ,tile-rect-hor ~dev/sprite.x ~rect.x2 LTH2 JMP2? POP2 + ,$hor ~dev/sprite.x ~rect.x2 LTH2 JMP2? POP2 ( incr ) ~dev/sprite.y #0008 ADD2 =dev/sprite.y - ,tile-rect-ver ~dev/sprite.y ~rect.y2 LTH2 JMP2? POP2 + ,$ver ~dev/sprite.y ~rect.y2 LTH2 JMP2? POP2 RTS @fill-rect ( x1 y1 x2 y2 color ) ( load ) =color =rect.y2 =rect.x2 DUP2 =dev/screen.y =rect.y1 DUP2 =dev/screen.x =rect.x1 - @fill-rect-ver + $ver ~rect.x1 =dev/screen.x - @fill-rect-hor + $hor ( draw ) ~color =dev/screen.color ( incr ) ~dev/screen.x #0001 ADD2 =dev/screen.x - ,fill-rect-hor ~dev/screen.x ~rect.x2 LTH2 JMP2? POP2 + ,$hor ~dev/screen.x ~rect.x2 LTH2 JMP2? POP2 ( incr ) ~dev/screen.y #0001 ADD2 =dev/screen.y - ,fill-rect-ver ~dev/screen.y ~rect.y2 LTH2 JMP2? POP2 + ,$ver ~dev/screen.y ~rect.y2 LTH2 JMP2? POP2 RTS @line-rect ( x1 y1 x2 y2 color ) ( load ) =color =rect.y2 =rect.x2 DUP2 =dev/screen.y =rect.y1 DUP2 =dev/screen.x =rect.x1 - @line-rect-hor + $hor ( incr ) ~dev/screen.x #0001 ADD2 =dev/screen.x ( draw ) ~rect.y1 =dev/screen.y ~color =dev/screen.color ( draw ) ~rect.y2 =dev/screen.y ~color =dev/screen.color - ,line-rect-hor ~dev/screen.x ~rect.x2 LTH2 JMP2? POP2 + ,$hor ~dev/screen.x ~rect.x2 LTH2 JMP2? POP2 ~rect.y1 =dev/screen.y - @line-rect-ver + $ver ( draw ) ~rect.x1 =dev/screen.x ~color =dev/screen.color ( draw ) ~rect.x2 =dev/screen.x ~color =dev/screen.color ( incr ) ~dev/screen.y #0001 ADD2 =dev/screen.y - ,line-rect-ver ~dev/screen.y ~rect.y2 #0001 ADD2 LTH2 JMP2? POP2 + ,$ver ~dev/screen.y ~rect.y2 #0001 ADD2 LTH2 JMP2? POP2 RTS @@ -111,20 +111,17 @@ RTS ( load ) =textarea.addr =textarea.color =dev/sprite.y =dev/sprite.x ~textarea.addr - @draw-textarea-left-loop + $loop ( draw ) DUP2 LDR #00 SWP #0008 MUL2 ,font ADD2 =dev/sprite.addr ~textarea.color =dev/sprite.color - ( detect linebreaks ) - DUP2 LDR #0d NEQ ,no-return ROT JMP2? POP2 + DUP2 LDR #0d NEQ ,$no-return ROT JMP2? POP2 ~textarea.x1 =dev/sprite.x ( incr ) ~dev/sprite.y #0008 ADD2 =dev/sprite.y ( decr ) ~dev/sprite.x #0008 SUB2 =dev/sprite.x - @no-return - + $no-return ( incr ) #0001 ADD2 ( incr ) ~dev/sprite.x #0008 ADD2 =dev/sprite.x - - DUP2 LDR #00 NEQ ,draw-textarea-left-loop ROT JMP2? POP2 + DUP2 LDR #00 NEQ ,$loop ROT JMP2? POP2 POP2 RTS diff --git a/projects/examples/dev.mouse.usm b/projects/examples/dev.mouse.usm index 33704cb..fdab735 100644 --- a/projects/examples/dev.mouse.usm +++ b/projects/examples/dev.mouse.usm @@ -129,11 +129,11 @@ RTS ( load ) =label.addr =label.color =dev/sprite.y =dev/sprite.x ~label.addr - @draw-label-loop + $loop ( draw ) DUP2 LDR #00 SWP #0008 MUL2 ,font ADD2 =dev/sprite.addr ~label.color =dev/sprite.color ( incr ) #0001 ADD2 ( incr ) ~dev/sprite.x #0008 ADD2 =dev/sprite.x - DUP2 #0001 ADD2 LDR #00 NEQ ,draw-label-loop ROT JMP2? POP2 + DUP2 #0001 ADD2 LDR #00 NEQ ,$loop ROT JMP2? POP2 POP2 RTS diff --git a/projects/software/nasu.usm b/projects/software/nasu.usm index 3f2cd99..d766360 100644 --- a/projects/software/nasu.usm +++ b/projects/software/nasu.usm @@ -270,7 +270,7 @@ RTS ( guides ) #00 =i ,font_hex =SPRT.addr - @draw-bankview-guides + $guides ~bankview.x #0010 SUB2 =SPRT.x ~bankview.y #00 ~i #08 MUL ADD2 =SPRT.y ( draw ) #02 =SPRT.color @@ -279,28 +279,28 @@ RTS ( draw ) #02 =SPRT.color ~SPRT.addr #0008 ADD2 =SPRT.addr ( incr ) ~i #01 ADD =i - ,draw-bankview-guides ~i #10 LTH JMP2? POP2 + ,$guides ~i #10 LTH JMP2? POP2 ( body ) ~bankview.x =SPRT.x ~bankview.y =SPRT.y #00 =pt.x #00 =pt.y ~bankview.addr =SPRT.addr - @draw-bankview-tiles-ver + $ver #00 =pt.x ~bankview.x =SPRT.x - @draw-bankview-tiles-hor + $hor ( draw ) #01 =SPRT.color - ,no-highlight ~SPRT.addr ~tileview.addr LTH2 JMP2? POP2 - ,no-highlight ~SPRT.addr ~tileview.addr #0018 ADD2 GTH2 JMP2? POP2 + ,$no-highlight ~SPRT.addr ~tileview.addr LTH2 JMP2? POP2 + ,$no-highlight ~SPRT.addr ~tileview.addr #0018 ADD2 GTH2 JMP2? POP2 ( draw ) #0c =SPRT.color - @no-highlight + $no-highlight ( incr ) ~SPRT.x #0008 ADD2 =SPRT.x ( incr ) ~SPRT.addr #0008 ADD2 =SPRT.addr ( incr ) ~pt.x #01 ADD =pt.x - ,draw-bankview-tiles-hor ~pt.x #10 LTH JMP2? POP2 + ,$hor ~pt.x #10 LTH JMP2? POP2 ( incr ) ~pt.y #01 ADD =pt.y ( incr ) ~SPRT.y #0008 ADD2 =SPRT.y - ,draw-bankview-tiles-ver ~pt.y #10 LTH JMP2? POP2 + ,$ver ~pt.y #10 LTH JMP2? POP2 RTS @@ -344,18 +344,18 @@ RTS ( line hor ) ~tileview.y #003f ADD2 =SCRN.y ~tileview.x =SCRN.x - @draw-hor + $line-hor ( draw ) #03 =SCRN.color ( incr ) ~SCRN.x #0002 ADD2 =SCRN.x - ~SCRN.x ~tileview.x #0082 ADD2 LTH2 ,draw-hor ROT JMP2? POP2 + ~SCRN.x ~tileview.x #0082 ADD2 LTH2 ,$line-hor ROT JMP2? POP2 ( line ver ) ~tileview.y =SCRN.y ~tileview.x #003f ADD2 =SCRN.x - @draw-ver + $line-ver ( draw ) #03 =SCRN.color ( incr ) ~SCRN.y #0002 ADD2 =SCRN.y - ~SCRN.y ~tileview.y #0081 ADD2 LTH2 ,draw-ver ROT JMP2? POP2 + ~SCRN.y ~tileview.y #0081 ADD2 LTH2 ,$line-ver ROT JMP2? POP2 ( rewind ) ~tileview.addr #0018 SUB2 =tileview.addr @@ -363,7 +363,7 @@ RTS ~tileview.y #0018 ADD2 =SPRT.y #00 =i - @draw-tileview-bytes + $bytes ~tileview.x #0088 ADD2 =SPRT.x ,font_hex #00 ~tileview.addr #00 ~i ADD2 LDR #f0 AND #04 ROR #08 MUL ADD2 =SPRT.addr ( draw ) #02 =SPRT.color @@ -372,7 +372,7 @@ RTS ( draw ) #02 =SPRT.color ( incr ) ~i #01 ADD =i ( incr ) ~SPRT.y #0008 ADD2 =SPRT.y - ,draw-tileview-bytes ~i #08 LTH JMP2? POP2 + ,$bytes ~i #08 LTH JMP2? POP2 ( operations ) @@ -387,27 +387,27 @@ RTS ~tileview.y =SPRT.y #00 =pt.x #00 =pt.y ~tileview.addr =SPRT.addr - @draw-tileview-tiles-ver + $tiles-ver #00 =pt.x ~tileview.x #0088 ADD2 =SPRT.x - @draw-tileview-tiles-hor + $tiles-hor ( draw ) #03 =SPRT.color ( incr ) ~SPRT.x #0008 ADD2 =SPRT.x ( incr ) ~SPRT.addr #0008 ADD2 =SPRT.addr ( incr ) ~pt.x #01 ADD =pt.x - ,draw-tileview-tiles-hor ~pt.x #02 LTH JMP2? POP2 + ,$tiles-hor ~pt.x #02 LTH JMP2? POP2 ( incr ) ~pt.y #01 ADD =pt.y ( incr ) ~SPRT.y #0008 ADD2 =SPRT.y - ,draw-tileview-tiles-ver ~pt.y #02 LTH JMP2? POP2 + ,$tiles-ver ~pt.y #02 LTH JMP2? POP2 RTS @draw-tileview-icn #00 =pt.x #00 =pt.y - @redraw-ver + $ver #00 =pt.x - @redraw-hor + $hor ( get bit ) ,blank_icn #00 ~tileview.addr #00 ~pt.y ADD2 LDR #07 ~pt.x SUB ROR #01 AND ( get bit ) @@ -415,11 +415,11 @@ RTS ( draw ) #01 =SPRT.color ( incr ) ~SPRT.x #0008 ADD2 =SPRT.x ( incr ) ~pt.x #01 ADD =pt.x - ,redraw-hor ~pt.x #08 LTH JMP2? POP2 + ,$hor ~pt.x #08 LTH JMP2? POP2 ( incr ) ~SPRT.y #0008 ADD2 =SPRT.y ( incr ) ~pt.y #01 ADD =pt.y ~SPRT.x #0040 SUB2 =SPRT.x - ,redraw-ver ~pt.y #08 LTH JMP2? POP2 + ,$ver ~pt.y #08 LTH JMP2? POP2 RTS @@ -470,17 +470,17 @@ RTS @line-rect ( x1 y1 x2 y2 color ) ( load ) =color =rect.y2 =rect.x2 DUP2 =SCRN.y =rect.y1 DUP2 =SCRN.x =rect.x1 - @line-rect-hor NOP + $hor NOP ( incr ) ~SCRN.x #0001 ADD2 =SCRN.x ( draw ) ~rect.y1 =SCRN.y ~color =SCRN.color ( draw ) ~rect.y2 =SCRN.y ~color =SCRN.color - ~SCRN.x ~rect.x2 LTH2 ^line-rect-hor MUL JMPS + ~SCRN.x ~rect.x2 LTH2 ^$hor MUL JMPS ~rect.y1 =SCRN.y - @line-rect-ver NOP + $ver NOP ( draw ) ~rect.x1 =SCRN.x ~color =SCRN.color ( draw ) ~rect.x2 =SCRN.x ~color =SCRN.color ( incr ) ~SCRN.y #0001 ADD2 =SCRN.y - ~SCRN.y ~rect.y2 #0001 ADD2 LTH2 ^line-rect-ver MUL JMPS + ~SCRN.y ~rect.y2 #0001 ADD2 LTH2 ^$ver MUL JMPS RTS diff --git a/projects/tests/loop.usm b/projects/tests/loop.usm index a2406ef..b9474a0 100644 --- a/projects/tests/loop.usm +++ b/projects/tests/loop.usm @@ -7,22 +7,24 @@ |0100 @RESET ( type: padded muljmp ) - - @loop1 NOP + @part1 + $loop NOP ~a #01 ADD =a - ~a #d0 LTH ^loop1 MUL JMPS + ~a #d0 LTH ^$loop MUL JMPS ( type: jmppop ) - @loop2 + @part2 + $loop ~b #01 ADD =b - ,loop2 ~b #d0 LTH JMP2? POP2 + ,$loop ~b #d0 LTH JMP2? POP2 ( type: padded jmppop ) - @loop3 NOP + @part3 + $loop NOP ~c #01 ADD =c - ~c #d0 LTH ^loop3 SWP JMPS? POP + ~c #d0 LTH ^$loop SWP JMPS? POP ~a =dev/console.byte ~b =dev/console.byte