mirror of
https://git.sr.ht/~rabbits/uxn
synced 2025-01-05 15:11:18 +00:00
Implemented local templated labels
This commit is contained in:
parent
59e6ced7b9
commit
b42cec41ef
8 changed files with 93 additions and 75 deletions
15
README.md
15
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
|
||||
|
|
31
assembler.c
31
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);
|
||||
|
|
|
@ -30,6 +30,9 @@ contexts:
|
|||
- match: '\&(\S+)\s?'
|
||||
scope: string.control
|
||||
pop: true
|
||||
- match: '\$(\S+)\s?'
|
||||
scope: string.control
|
||||
pop: true
|
||||
|
||||
# Special
|
||||
|
||||
|
|
|
@ -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 ]
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue