Compare commits

..

2 Commits

Author SHA1 Message Date
2fd094bbc2 *.vs.asm: use semicolon syntax 2025-10-20 22:57:51 -05:00
306de6541d assembler: add minus token; disable eol tokens 2025-10-20 22:48:43 -05:00
13 changed files with 82 additions and 82 deletions

View File

@ -1 +1 @@
out[0].xyzw = VE_ADD input[0].xyzw input[0].0000 input[0].0000 out[0].xyzw = VE_ADD input[0].xyzw input[0].0000 input[0].0000 ;

1
drm/clear_nop.vs.inc Normal file
View File

@ -0,0 +1 @@
0x00f00203, 0x00d10001, 0x01248001, 0x01248001,

View File

@ -1,65 +1,65 @@
; CONST[0] = {0.159155, 0.5, 6.283185, -3.141593} # CONST[0] = {0.159155, 0.5, 6.283185, -3.141593}
; CONST[1] = {theta1, theta2, 0.2, 0.5} # CONST[1] = {theta1, theta2, 0.2, 0.5}
; each instruction is only allowed to use a single unique `const` address # each instruction is only allowed to use a single unique `const` address
; #
; instructions may use multiple `temp` addresses, so const[1] is moved to # instructions may use multiple `temp` addresses, so const[1] is moved to
; temp[0]: # temp[0]:
; #
temp[0].xy = VE_ADD const[1].xy__ const[1].00__ temp[0].xy = VE_ADD const[1].xy__ const[1].00__ ;
; ME_SIN and ME_COS are clamped to the range -π to +π prior to the sin/cos # ME_SIN and ME_COS are clamped to the range -π to +π prior to the sin/cos
; calculation. # calculation.
; #
; This 3-instruction sequence linearly remaps the range [-∞,+∞] to [-π,+π] # This 3-instruction sequence linearly remaps the range [-,+] to [-π,+π]
temp[0].xy = VE_MAD temp[0].xy__ const[0].xx__ const[0].yy__ temp[0].xy = VE_MAD temp[0].xy__ const[0].xx__ const[0].yy__ ;
temp[0].xy = VE_FRC temp[0].xy__ temp[0].xy = VE_FRC temp[0].xy__ ;
temp[0].xy = VE_MAD temp[0].xy__ const[0].zz__ const[0].ww__ temp[0].xy = VE_MAD temp[0].xy__ const[0].zz__ const[0].ww__ ;
; sin and cos # sin and cos
temp[3].x = ME_SIN temp[0].___x temp[3].x = ME_SIN temp[0].___x ;
temp[3].y = ME_COS temp[0].___x temp[3].y = ME_COS temp[0].___x ;
temp[4].x = ME_SIN temp[0].___y temp[4].x = ME_SIN temp[0].___y ;
temp[4].y = ME_COS temp[0].___y temp[4].y = ME_COS temp[0].___y ;
; temp[3] now contains: # temp[3] now contains:
; temp[3] = {sin(theta1), cos(theta1), sin(theta2), cos(theta2)} # temp[3] = {sin(theta1), cos(theta1), sin(theta2), cos(theta2)}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; #########################################################################
; first rotation: X-axis rotation: # first rotation: X-axis rotation:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; #########################################################################
; y_ = (-z0 * st1) # y_ = (-z0 * st1)
; z_ = ( z0 * ct1) # z_ = ( z0 * ct1)
temp[1].yz = VE_MUL input[0]._-zz_ temp[3]._xy_ temp[1].yz = VE_MUL input[0]._-zz_ temp[3]._xy_ ;
; x1 = (x0 * 1 + 0) # x1 = (x0 * 1 + 0)
; y1 = (y0 * ct1 + nz0st1) # y1 = (y0 * ct1 + nz0st1)
; z1 = (y0 * st1 + z0ct1) # z1 = (y0 * st1 + z0ct1)
temp[1].xyz = VE_MAD input[0].xyy_ temp[3].1yx_ temp[1].0yz_ temp[1].xyz = VE_MAD input[0].xyy_ temp[3].1yx_ temp[1].0yz_ ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; #########################################################################
; second rotation: Y-axis rotation: # second rotation: Y-axis rotation:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; #########################################################################
; x_ = (-z1 * st2) # x_ = (-z1 * st2)
; z_ = ( z1 * ct2) # z_ = ( z1 * ct2)
temp[2].xz = VE_MUL temp[1].-z_z_ temp[4].x_y_ temp[2].xz = VE_MUL temp[1].-z_z_ temp[4].x_y_ ;
; x2 = (x1 * ct2 + nz1st2) # x2 = (x1 * ct2 + nz1st2)
; y2 = (y1 * 1 + 0) # y2 = (y1 * 1 + 0)
; z2 = (x1 * st2 + z1ct2) # z2 = (x1 * st2 + z1ct2)
temp[2].xyz = VE_MAD temp[1].xyx_ temp[4].y1x_ temp[2].x0z_ temp[2].xyz = VE_MAD temp[1].xyx_ temp[4].y1x_ temp[2].x0z_ ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; #########################################################################
; scale # scale
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; #########################################################################
temp[3].xyz = VE_MAD temp[2].xyz_ const[1].zzz_ const[1].00w_ temp[3].xyz = VE_MAD temp[2].xyz_ const[1].zzz_ const[1].00w_ ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; #########################################################################
; output # output
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; #########################################################################
out[0].xyzw = VE_MUL temp[3].xyzz temp[3].11-z1 out[0].xyzw = VE_MUL temp[3].xyzz temp[3].11-z1 ;
out[1].xyzw = VE_ADD input[1].xyzw input[1].0000 out[1].xyzw = VE_ADD input[1].xyzw input[1].0000 ;

View File

@ -1,5 +1,5 @@
0x00300003, 0x01f90022, 0x01fc8022, 0x01ffe022, 0x00300003, 0x01f90022, 0x01fc8022, 0x01ffe022,
0x00300004, 0x01f90000, 0x01f90002, 0x01f92002, 0x00300004, 0x01f90000, 0x01f80002, 0x01f92002,
0x00300006, 0x01f90000, 0x01ffe000, 0x01ffe000, 0x00300006, 0x01f90000, 0x01ffe000, 0x01ffe000,
0x00300004, 0x01f90000, 0x01fa4002, 0x01fb6002, 0x00300004, 0x01f90000, 0x01fa4002, 0x01fb6002,
0x00106050, 0x003fe000, 0x01ffe000, 0x01ffe000, 0x00106050, 0x003fe000, 0x01ffe000, 0x01ffe000,
@ -7,7 +7,7 @@
0x00108050, 0x007fe000, 0x01ffe000, 0x01ffe000, 0x00108050, 0x007fe000, 0x01ffe000, 0x01ffe000,
0x00208051, 0x007fe000, 0x01ffe000, 0x01ffe000, 0x00208051, 0x007fe000, 0x01ffe000, 0x01ffe000,
0x00602002, 0x05d2e001, 0x01c8e060, 0x01ffe060, 0x00602002, 0x05d2e001, 0x01c8e060, 0x01ffe060,
0x00702080, 0x01c90001, 0x01c1a060, 0x01d18020, 0x00702004, 0x01c90001, 0x01c1a060, 0x01d18020,
0x00504002, 0x03d74020, 0x01cf0080, 0x01ffe080, 0x00504002, 0x03d74020, 0x01cf0080, 0x01ffe080,
0x00704080, 0x01c10020, 0x01c52080, 0x01d40040, 0x00704080, 0x01c10020, 0x01c52080, 0x01d40040,
0x00706004, 0x01d10040, 0x01d24022, 0x01dc8022, 0x00706004, 0x01d10040, 0x01d24022, 0x01dc8022,

View File

@ -6,19 +6,19 @@
# instructions may use multiple `temp` addresses, so const[1] is moved to # instructions may use multiple `temp` addresses, so const[1] is moved to
# temp[0]: # temp[0]:
# #
temp[0].x = VE_ADD const[1].x___ const[1].0___ temp[0].x = VE_ADD const[1].x___ const[1].0___ ;
# ME_SIN and ME_COS are clamped to the range -π to +π prior to the sin/cos # ME_SIN and ME_COS are clamped to the range -π to +π prior to the sin/cos
# calculation. # calculation.
# #
# This 3-instruction sequence linearly remaps the range [-,+] to [-π,+π] # This 3-instruction sequence linearly remaps the range [-,+] to [-π,+π]
temp[1].x = VE_MAD temp[0].x___ const[0].x___ const[0].y___ temp[1].x = VE_MAD temp[0].x___ const[0].x___ const[0].y___ ;
temp[2].x = VE_FRC temp[1].x___ temp[2].x = VE_FRC temp[1].x___ ;
temp[3].x = VE_MAD temp[2].x___ const[0].z___ const[0].w___ temp[3].x = VE_MAD temp[2].x___ const[0].z___ const[0].w___ ;
temp[4].x = ME_SIN temp[3].___x temp[4].x = ME_SIN temp[3].___x ;
temp[4].y = ME_COS temp[3].___x temp[4].y = ME_COS temp[3].___x ;
# with sin and cos calculated, this now ordinary two-dimensional rotation: # with sin and cos calculated, this now ordinary two-dimensional rotation:
# #
@ -26,5 +26,5 @@ temp[4].y = ME_COS temp[3].___x
# y = position.x * sint + position.y * cost # y = position.x * sint + position.y * cost
# z = 0 # z = 0
# w = 1 # w = 1
temp[5].xy = VE_MUL input[0].yy__ temp[4].xy__ temp[5].xy = VE_MUL input[0].yy__ temp[4].xy__ ;
out[0].xyzw = VE_MAD input[0].xx01 temp[4].yx01 temp[5].-xy00 out[0].xyzw = VE_MAD input[0].xx01 temp[4].yx01 temp[5].-xy00 ;

View File

@ -1,3 +1,3 @@
# CONST[0] = { 1.3333 , _, _, _ } # CONST[0] = { 1.3333 , _, _, _ }
out[1].xy = VE_MUL input[0].xy__ const[0].x1__ out[1].xy = VE_MUL input[0].xy__ const[0].x1__ ;
out[0].xyzw = VE_ADD input[0].xyz1 input[0].0000 out[0].xyzw = VE_ADD input[0].xyz1 input[0].0000 ;

View File

@ -1,2 +1,2 @@
0x00302203, 0x01f90001, 0x01248001, 0x01248001, 0x00302202, 0x01f90001, 0x01fd0002, 0x01ffe002,
0x00f00203, 0x01510001, 0x01248001, 0x01248001, 0x00f00203, 0x01510001, 0x01248001, 0x01ffe001,

View File

@ -18,7 +18,7 @@ def print_error(filename, buf, e):
if i == token.col: if i == token.col:
sys.stderr.write(RED) sys.stderr.write(RED)
sys.stderr.write(c) sys.stderr.write(c)
if i == token.col + len(token.lexeme): if i == token.col + len(token.lexeme) - 1:
wrote_default = True wrote_default = True
sys.stderr.write(DEFAULT) sys.stderr.write(DEFAULT)
if not wrote_default: if not wrote_default:

View File

@ -8,7 +8,7 @@ from assembler.fs.emitter import emit_instruction
from assembler.error import print_error from assembler.error import print_error
def frontend_inner(buf): def frontend_inner(buf):
lexer = Lexer(buf, find_keyword, emit_newlines=False) lexer = Lexer(buf, find_keyword, emit_newlines=False, minus_is_token=True)
tokens = list(lexer.lex_tokens()) tokens = list(lexer.lex_tokens())
parser = Parser(tokens) parser = Parser(tokens)
for ins_ast in parser.instructions(): for ins_ast in parser.instructions():

View File

@ -103,7 +103,7 @@ class Parser(BaseParser):
return False return False
def is_neg(self): def is_neg(self):
result = self.match(TT.identifier) and self.peek().lexeme == b'-' result = self.match(TT.minus)
if result: if result:
self.advance() self.advance()
return result return result
@ -118,17 +118,12 @@ class Parser(BaseParser):
neg = self.is_neg() neg = self.is_neg()
abs = self.is_abs() abs = self.is_abs()
if neg:
self.consume(TT.left_paren, "expected left paren")
sel_keyword = self.consume(TT.keyword, "expected sel keyword") sel_keyword = self.consume(TT.keyword, "expected sel keyword")
self.consume(TT.dot, "expected dot") self.consume(TT.dot, "expected dot")
swizzle_identifier = self.consume(TT.identifier, "expected swizzle identifier") swizzle_identifier = self.consume(TT.identifier, "expected swizzle identifier")
if abs: if abs:
self.consume(TT.bar, "expected bar") self.consume(TT.bar, "expected bar")
if neg:
self.consume(TT.right_paren, "expected right paren")
mod_table = { mod_table = {
# (neg, abs) # (neg, abs)
@ -211,7 +206,7 @@ src0.a = float(0), src1.a = float(0), src2.a = float(0), srcp.a = neg2, src0.rgb
out[0].none = temp[0].none = MAD src0.r src0.r src0.r , out[0].none = temp[0].none = MAD src0.r src0.r src0.r ,
out[0].none = temp[0].r = DP3 src0.rg0 src0.rg0 src0.rrr ; out[0].none = temp[0].r = DP3 src0.rg0 src0.rg0 src0.rrr ;
""" """
lexer = Lexer(buf, find_keyword, emit_newlines=False) lexer = Lexer(buf, find_keyword, emit_newlines=False, minus_is_token=True)
tokens = list(lexer.lex_tokens()) tokens = list(lexer.lex_tokens())
parser = Parser(tokens) parser = Parser(tokens)
from pprint import pprint from pprint import pprint

View File

@ -512,7 +512,7 @@ src0.a = float(0), src0.rgb = temp[0] , srcp.a = neg :
out[0].none = temp[0].none = MAD src0.r src0.r src0.r , out[0].none = temp[0].none = MAD src0.r src0.r src0.r ,
out[0].none = temp[0].r = DP3 src0.rg0 src0.rg0 ; out[0].none = temp[0].r = DP3 src0.rg0 src0.rg0 ;
""" """
lexer = Lexer(buf, find_keyword, emit_newlines=False) lexer = Lexer(buf, find_keyword, emit_newlines=False, minus_is_token=True)
tokens = list(lexer.lex_tokens()) tokens = list(lexer.lex_tokens())
parser = Parser(tokens) parser = Parser(tokens)
try: try:

View File

@ -20,6 +20,7 @@ class TT(Enum):
semicolon = auto() semicolon = auto()
bar = auto() bar = auto()
comma = auto() comma = auto()
minus = auto()
@dataclass @dataclass
class Token: class Token:
@ -41,7 +42,9 @@ class LexerError(Exception):
pass pass
class Lexer: class Lexer:
def __init__(self, buf: memoryview, find_keyword, emit_newlines=True): def __init__(self, buf: memoryview, find_keyword,
emit_newlines=False,
minus_is_token=False):
self.start_ix = 0 self.start_ix = 0
self.current_ix = 0 self.current_ix = 0
self.buf = memoryview(buf) self.buf = memoryview(buf)
@ -49,6 +52,7 @@ class Lexer:
self.col = 0 self.col = 0
self.find_keyword = find_keyword self.find_keyword = find_keyword
self.emit_newlines = emit_newlines self.emit_newlines = emit_newlines
self.minus_is_token = minus_is_token
def at_end_p(self): def at_end_p(self):
return self.current_ix >= len(self.buf) return self.current_ix >= len(self.buf)
@ -108,6 +112,8 @@ class Lexer:
return Token(*self.pos(), TT.semicolon, self.lexeme()) return Token(*self.pos(), TT.semicolon, self.lexeme())
elif c == ord(','): elif c == ord(','):
return Token(*self.pos(), TT.comma, self.lexeme()) return Token(*self.pos(), TT.comma, self.lexeme())
elif self.minus_is_token and c == ord('-'):
return Token(*self.pos(), TT.minus, self.lexeme())
elif c == ord('#'): elif c == ord('#'):
while not self.at_end_p() and self.peek() != ord('\n'): while not self.at_end_p() and self.peek() != ord('\n'):
self.advance() self.advance()

View File

@ -174,21 +174,19 @@ class Parser(BaseParser):
return Source(source_type, offset, source_swizzle) return Source(source_type, offset, source_swizzle)
def instruction(self): def instruction(self):
while self.match(TT.eol):
self.advance()
first_token = self.peek() first_token = self.peek()
destination_op = self.destination_op() destination_op = self.destination_op()
source0 = self.source() source0 = self.source()
if self.match(TT.eol) or self.match(TT.eof): if self.match(TT.semicolon) or self.match(TT.eof):
source1 = None source1 = None
else: else:
source1 = self.source() source1 = self.source()
if self.match(TT.eol) or self.match(TT.eof): if self.match(TT.semicolon) or self.match(TT.eof):
source2 = None source2 = None
else: else:
source2 = self.source() source2 = self.source()
last_token = self.peek(-1) last_token = self.peek(-1)
self.consume_either(TT.eol, TT.eof, "expected newline or EOF") self.consume(TT.semicolon, "expected semicolon")
return ( return (
Instruction(destination_op, source0, source1, source2), Instruction(destination_op, source0, source1, source2),
(first_token.start_ix, last_token.start_ix + len(last_token.lexeme)) (first_token.start_ix, last_token.start_ix + len(last_token.lexeme))