From 3974d3bf5dbe7e91fc3b8a5ca2d65b924c570c89 Mon Sep 17 00:00:00 2001
From: g012 <leclerc.pascal@gmail.com>
Date: Mon, 18 Sep 2017 16:01:52 +0200
Subject: [PATCH] Added relative opcodes.

---
 6502.lua | 23 +++++++++++++++++++-
 asm.lua  | 64 ++++++++++++++++++++++++++++----------------------------
 l65.lua  | 10 +++++----
 3 files changed, 60 insertions(+), 37 deletions(-)

diff --git a/6502.lua b/6502.lua
index cea8472..4f6d1da 100644
--- a/6502.lua
+++ b/6502.lua
@@ -391,7 +391,8 @@ M.word = function(...)
     table.insert(M.section_current.instructions, { data=data, size=#data*2, asbin=asbin })
 end
 
-local op,cycles_def = function(code, cycles, extra_on_crosspage)
+local op,cycles_def
+op = function(code, cycles, extra_on_crosspage)
     return { opc=code, cycles=cycles or cycles_def, xcross=extra_on_crosspage or 0 }
 end
 cycles_def=2 local opimp={
@@ -488,5 +489,25 @@ for k,v in pairs(opabs) do
         table.insert(M.section_current.instructions, ins)
     end
 end
+cycles_def=2 local oprel={
+    bcc=op(0x90), bcs=op(0xb0), beq=op(0xf0), bmi=op(0x30), bne=op(0xd0), bpl=op(0x10), bvc=op(0x50), bvs=op(0x70),
+} M.oprel = oprel
+for k,v in pairs(oprel) do
+    M[k .. 'rel'] = function(label)
+        local parent = M.label_current
+        local asbin = function(b)
+            local x = label
+            if type(x) == 'function' then x=x() end
+            if type(x) == 'string' then
+                if x:sub(1,1) == '_' then x = parent .. x end
+                x = symbols[x]
+            end
+            if type(x) ~= 'number' then error("unresolved branch target: " .. x) end
+            if x < -128 or x > 127 then error("branch target out of range: " .. x) end
+            b[#b+1]=v.opc b[#b+1]=x&0xff
+        end
+        table.insert(M.section_current.instructions, { size=2, cycles=2, asbin=asbin })
+    end
+end
 
 return M
diff --git a/asm.lua b/asm.lua
index 129c07b..e313e80 100644
--- a/asm.lua
+++ b/asm.lua
@@ -19,16 +19,16 @@ lda = 5 if lda < 6 then print('yep') end
 
 local function ptr_table(label, ...)
     local vals = {...}
-    section(label .. "_lo") byte_lo(vals)
-    section(label .. "_hi") byte_hi(vals)
+    section{label .. "_lo", align=16} byte_lo(vals)
+    section{label .. "_hi", align=16} byte_hi(vals)
 end
 
 charset(" abcdefghijklmnopqrstuvwxyz-")
-section(function(o) return o+("message2") end) byte(4, "test", 0)
+section("message2") byte(4, "test", 0)
 charset()
-section(function(o) return o+("message") end) byte(4, "test", 0)
+section("message") byte(4, "test", 0)
 
-section(function(o) return o+("data") end)
+section("data")
     do crosspage()
         byte(1, 2) byte(3, 4) endpage()
     end
@@ -43,7 +43,7 @@ ptr_table("ptrs", message, data, 0)
 --section{ "toto", align = 256, offset = 16 }
 --section{ "toto", org = 0xf100 }
 --section "waitForIntim"
-section(function(o) return o+("waitForIntim") end) --alt short syntax when no other option
+section("waitForIntim") --alt short syntax when no other option
     -- n_{ a=INTIM } ?
     --lda(INTIM) -- or a=INTIM
     --bne "waitForIntim"
@@ -53,15 +53,15 @@ section(function(o) return o+("waitForIntim") end) --alt short syntax when no ot
     ldximm (function(o) return o+(15) end,3)
 
     local kernel_cycles,kernel_size
-    hook(function() kernel_cycles=cycles kernel_size=size end)
+    table.insert(section_current.instructions, { asbin=function() kernel_cycles=cycles kernel_size=size end })
 
-    ldaabs(function(o) return o+( data) end)
-    ldaabs(function(o) return o+( data) end,5)
-    ldaabx(function(o) return o+( data) end,5)
-    ldaaby(function(o) return o+( data) end,5)
-    ldaabs(function(o) return o+( data+3) end,12)
-    ldaabx(function(o) return o+( data+3) end,12)
-    ldaaby(function(o) return o+( data+3) end,12)
+    ldazab(function(o) return o+( data) end)
+    ldazab(function(o) return o+( data) end,5)
+    ldazax(function(o) return o+( data) end,5)
+    ldazay(function(o) return o+( data) end,5)
+    ldazab(function(o) return o+( data+3) end,12)
+    ldazax(function(o) return o+( data+3) end,12)
+    ldazay(function(o) return o+( data+3) end,12)
     ldainx (function(o) return o+(INTIM) end,5)
     ldainx (function(a) return a+2 end,INTIM)
     ldainy (function(o) return o+(INTIM) end,5)
@@ -71,40 +71,40 @@ section(function(o) return o+("waitForIntim") end) --alt short syntax when no ot
     jmpind (function(o) return o+(INTIM-4) end)
 
     -- cycles are counted without taking any branch
-    hook(function() return print('kernel cycles: ', cycles-kernel_cycles, 'kernel size: ', size-kernel_size) end)
+    table.insert(section_current.instructions, { asbin=function() print('kernel cycles: ', cycles-kernel_cycles, 'kernel size: ', size-kernel_size) end })
 
-    ldaabs( function(c) return data * c end, v)
-    ldaabs( function(c) return data*c end, v)
-    local f = function(c) return data*c end v=5 ldaabs(f,v) v=12 ldaabs(f,v)
+    ldazab( function(c) return data * c end, v)
+    ldazab( function(c) return data*c end, v)
+    local f = function(c) return data*c end v=5 ldazab(f,v) v=12 ldazab(f,v)
     local g = function() return function(c) return data * c end end
 
-    ldaabs(g(),v)
-    ldaabs( f,v)
-    ldaabx (function(o) return o+(_toto+15) end,16)
+    ldazab(g(),v)
+    ldazab( f,v)
+    ldazax (function(o) return o+(_toto+15) end,16)
     ldaimm (15)
 
     do samepage()
         ldaimm (function(o) return o+(0xac) end)
         ldaimm (function(o) return o+(INTIM) end)
-        ldaabs(function(o) return o+( 0xbeef) end)
+        ldazab(function(o) return o+( 0xbeef) end)
+        ldazab(function(o) return o+( INTIM) end)
         ldaabs(function(o) return o+( INTIM) end)
-        ldaabsw(function(o) return o+( INTIM) end)
-        ldaabx(function(o) return o+( INTIM) end)
-        ldaaby(function(o) return o+( INTIM) end)
+        ldazax(function(o) return o+( INTIM) end)
+        ldazay(function(o) return o+( INTIM) end)
         ldainx (function(o) return o+(INTIM) end)
         ldainy (function(o) return o+(INTIM) end) endpage()
     end
 
     aslimp()
-    aslabs(function(o) return o+( INTIM) end)
+    aslzab(function(o) return o+( INTIM) end)
     aslimp()
-label(function(o) return o+("_toto") end)
-    bnerel(function(o) return o+( "test") end)
-    bnerel(function(o) return o+( "waitForIntim") end)
-    bnerel(function(o) return o+( f()) end)
-    bnerel(function(o) return o+( "_toto") end)
+label("_toto")
+    bnerel( "test")
+    bnerel( "waitForIntim")
+    bnerel( f())
+    bnerel( "_toto")
 
-    jamimp() aslimp() lsrimp() ldximm (function(o) return o+(16) end) ldyabs(function(o) return o+( 0xf0f0) end)
+    jamimp() aslimp() lsrimp() ldximm (function(o) return o+(16) end) ldyzab(function(o) return o+( 0xf0f0) end)
 
     rtsimp()
 
diff --git a/l65.lua b/l65.lua
index 11b3532..5742b51 100644
--- a/l65.lua
+++ b/l65.lua
@@ -1191,7 +1191,9 @@ local function ParseLua(src)
             local op_var = {
                 AstType='VarExpr', Name=name, Variable={ IsGlobal=true, Name=name, Scope=CreateScope(scope) }, Tokens = { t('Ident', name, params.func_white) }
             }
-            if #args > 0 and ( (opcode_arg_encapsulate_on and not inverse_encapsulate) or (not opcode_arg_encapsulate_on and inverse_encapsulate) ) and args[1].AstType ~= 'Function' then
+            local encapsulate = params.encapsulate
+            if encapsulate == nil then encapsulate = opcode_arg_encapsulate_on end
+            if #args > 0 and ( (encapsulate and not inverse_encapsulate) or (not encapsulate and inverse_encapsulate) ) and args[1].AstType ~= 'Function' then
                 local inner_call_scope = CreateScope(op_var.Variable.Scope)
                 local inner_add = {
                     AstType='BinopExpr', Op='+', OperatorPrecedence=10, Tokens={ t('Symbol', '+') },
@@ -1251,12 +1253,12 @@ local function ParseLua(src)
             if not tok:Is('Ident') then return false, GenerateError("<ident> expected.") end
             local label_name = tok:Get(tokenList)
             label_name = as_string_expr(label_name, label_name.Data)
-            stat = emit_call{name = 'section', args = {label_name}}
+            stat = emit_call{name = 'section', args = {label_name}, encapsulate=false}
         elseif tok:ConsumeSymbol('@', tokenList) then
             if not tok:Is('Ident') then return false, GenerateError("<ident> expected.") end
             local label_name = tok:Get(tokenList)
             label_name = as_string_expr(label_name, label_name.Data)
-            stat = emit_call{name = 'label', args = {label_name}}
+            stat = emit_call{name = 'label', args = {label_name}, encapsulate=false}
         end end
 
         -- new statements
@@ -1297,7 +1299,7 @@ local function ParseLua(src)
                     if expr.AstType == 'VarExpr' and expr.Variable.IsGlobal then
                         expr = as_string_expr(expr, expr.Name)
                     end
-                    stat = emit_call{name=op .. "rel", args={expr}} break
+                    stat = emit_call{name=op .. "rel", args={expr}, encapsulate=false} break
                 end
                 if opcode_immediate[op] and tok:ConsumeSymbol('#', tokenList) then
                     if tok:ConsumeSymbol('!', tokenList) then inverse_encapsulate = true end