Browse Source

DynASM/ARM64: Various fixes.

Mike Pall 10 years ago
parent
commit
a13dfd66c3
2 changed files with 50 additions and 17 deletions
  1. 9 2
      dynasm/dasm_arm64.h
  2. 41 15
      dynasm/dasm_arm64.lua

+ 9 - 2
dynasm/dasm_arm64.h

@@ -22,7 +22,7 @@ enum {
   DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
   DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
   /* The following actions also have an argument. */
   /* The following actions also have an argument. */
   DASM_REL_PC, DASM_LABEL_PC,
   DASM_REL_PC, DASM_LABEL_PC,
-  DASM_IMM, DASM_IMM12, DASM_IMM13W, DASM_IMM13X, DASM_IMML,
+  DASM_IMM, DASM_IMM6, DASM_IMM12, DASM_IMM13W, DASM_IMM13X, DASM_IMML,
   DASM__MAX
   DASM__MAX
 };
 };
 
 
@@ -290,6 +290,10 @@ void dasm_put(Dst_DECL, int start, ...)
 #endif
 #endif
 	b[pos++] = n;
 	b[pos++] = n;
 	break;
 	break;
+      case DASM_IMM6:
+	CK((n >> 6) == 0, RANGE_I);
+	b[pos++] = n;
+	break;
       case DASM_IMM12:
       case DASM_IMM12:
 	CK(dasm_imm12((unsigned int)n) != -1, RANGE_I);
 	CK(dasm_imm12((unsigned int)n) != -1, RANGE_I);
 	b[pos++] = n;
 	b[pos++] = n;
@@ -369,7 +373,7 @@ int dasm_link(Dst_DECL, size_t *szp)
 	case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
 	case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
 	case DASM_REL_LG: case DASM_REL_PC: pos++; break;
 	case DASM_REL_LG: case DASM_REL_PC: pos++; break;
 	case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
 	case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
-	case DASM_IMM: case DASM_IMM12: case DASM_IMM13W:
+	case DASM_IMM: case DASM_IMM6: case DASM_IMM12: case DASM_IMM13W:
 	case DASM_IMML: pos++; break;
 	case DASM_IMML: pos++; break;
 	case DASM_IMM13X: pos += 2; break;
 	case DASM_IMM13X: pos += 2; break;
 	}
 	}
@@ -449,6 +453,9 @@ int dasm_encode(Dst_DECL, void *buffer)
 	case DASM_IMM:
 	case DASM_IMM:
 	  cp[-1] |= ((n>>((ins>>10)&31)) & ((1<<((ins>>5)&31))-1)) << (ins&31);
 	  cp[-1] |= ((n>>((ins>>10)&31)) & ((1<<((ins>>5)&31))-1)) << (ins&31);
 	  break;
 	  break;
+	case DASM_IMM6:
+	  cp[-1] |= ((n&31) << 19) | ((n&32) << 26);
+	  break;
 	case DASM_IMM12:
 	case DASM_IMM12:
 	  cp[-1] |= (dasm_imm12((unsigned int)n) << 10);
 	  cp[-1] |= (dasm_imm12((unsigned int)n) << 10);
 	  break;
 	  break;

+ 41 - 15
dynasm/dasm_arm64.lua

@@ -39,7 +39,7 @@ local wline, werror, wfatal, wwarn
 local action_names = {
 local action_names = {
   "STOP", "SECTION", "ESC", "REL_EXT",
   "STOP", "SECTION", "ESC", "REL_EXT",
   "ALIGN", "REL_LG", "LABEL_LG",
   "ALIGN", "REL_LG", "LABEL_LG",
-  "REL_PC", "LABEL_PC", "IMM", "IMM12", "IMM13W", "IMM13X", "IMML",
+  "REL_PC", "LABEL_PC", "IMM", "IMM6", "IMM12", "IMM13W", "IMM13X", "IMML",
 }
 }
 
 
 -- Maximum number of section buffer positions for dasm_put().
 -- Maximum number of section buffer positions for dasm_put().
@@ -274,10 +274,10 @@ end
 
 
 local function parse_reg_base(expr)
 local function parse_reg_base(expr)
   if expr == "sp" then return 0x3e0 end
   if expr == "sp" then return 0x3e0 end
-  local base = parse_reg(expr)
+  local base, tp = parse_reg(expr)
   if parse_reg_type ~= "x" then werror("bad register type") end
   if parse_reg_type ~= "x" then werror("bad register type") end
   parse_reg_type = false
   parse_reg_type = false
-  return shl(base, 5)
+  return shl(base, 5), tp
 end
 end
 
 
 local parse_ctx = {}
 local parse_ctx = {}
@@ -387,7 +387,8 @@ local function parse_imm6(imm)
     end
     end
     werror("out of range immediate `"..imm.."'")
     werror("out of range immediate `"..imm.."'")
   else
   else
-    werror("NYI imm6 action")
+    waction("IMM6", 0, imm)
+    return 0
   end
   end
 end
 end
 
 
@@ -460,12 +461,23 @@ local function parse_cond(expr, inv)
 end
 end
 
 
 local function parse_load(params, nparams, n, op)
 local function parse_load(params, nparams, n, op)
-  local pn = params[n]
-  local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$")
-  if not p1 then werror("expected address operand") end
   if params[n+2] then werror("too many operands") end
   if params[n+2] then werror("too many operands") end
+  local pn, p2 = params[n], params[n+1]
+  local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$")
+  if not p1 then
+    if not p2 then
+      local reg, tailr = match(pn, "^([%w_:]+)%s*(.*)$")
+      if reg and tailr ~= "" then
+	local base, tp = parse_reg_base(reg)
+	if tp then
+	  waction("IMML", 0, format(tp.ctypefmt, tailr))
+	  return op + base
+	end
+      end
+    end
+    werror("expected address operand")
+  end
   local scale = shr(op, 30)
   local scale = shr(op, 30)
-  local p2 = params[n+1]
   if p2 then
   if p2 then
     if wb == "!" then werror("bad use of '!'") end
     if wb == "!" then werror("bad use of '!'") end
     op = op + parse_reg_base(p1) + parse_imm(p2, 9, 12, 0, true) + 0x400
     op = op + parse_reg_base(p1) + parse_imm(p2, 9, 12, 0, true) + 0x400
@@ -520,12 +532,23 @@ local function parse_load(params, nparams, n, op)
 end
 end
 
 
 local function parse_load_pair(params, nparams, n, op)
 local function parse_load_pair(params, nparams, n, op)
-  local pn = params[n]
-  local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$")
-  if not p1 then werror("expected address operand") end
   if params[n+2] then werror("too many operands") end
   if params[n+2] then werror("too many operands") end
+  local pn, p2 = params[n], params[n+1]
   local scale = shr(op, 30) == 0 and 2 or 3
   local scale = shr(op, 30) == 0 and 2 or 3
-  local p2 = params[n+1]
+  local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$")
+  if not p1 then
+    if not p2 then
+      local reg, tailr = match(pn, "^([%w_:]+)%s*(.*)$")
+      if reg and tailr ~= "" then
+	local base, tp = parse_reg_base(reg)
+	if tp then
+	  waction("IMM", 32768+7*32+15+scale*1024, format(tp.ctypefmt, tailr))
+	  return op + base + 0x01000000
+	end
+      end
+    end
+    werror("expected address operand")
+  end
   if p2 then
   if p2 then
     if wb == "!" then werror("bad use of '!'") end
     if wb == "!" then werror("bad use of '!'") end
     op = op + 0x00800000
     op = op + 0x00800000
@@ -724,7 +747,7 @@ map_op = {
 
 
   sxtb_2 = "13001c00DNw|93401c00DNx",
   sxtb_2 = "13001c00DNw|93401c00DNx",
   sxth_2 = "13003c00DNw|93403c00DNx",
   sxth_2 = "13003c00DNw|93403c00DNx",
-  sxtw_2 = "93407c00DNx",
+  sxtw_2 = "93407c00DxNw",
   uxtb_2 = "53001c00DNw",
   uxtb_2 = "53001c00DNw",
   uxth_2 = "53003c00DNw",
   uxth_2 = "53003c00DNw",
 
 
@@ -851,7 +874,7 @@ map_op = {
 }
 }
 
 
 for cond,c in pairs(map_cond) do
 for cond,c in pairs(map_cond) do
-  map_op["b"..cond.."_1"] = tohex(0x54000000+c)
+  map_op["b"..cond.."_1"] = tohex(0x54000000+c).."B"
 end
 end
 
 
 ------------------------------------------------------------------------------
 ------------------------------------------------------------------------------
@@ -957,13 +980,16 @@ function op_template(params, template, nparams)
   -- A single opcode needs a maximum of 3 positions.
   -- A single opcode needs a maximum of 3 positions.
   if secpos+3 > maxsecpos then wflush() end
   if secpos+3 > maxsecpos then wflush() end
   local pos = wpos()
   local pos = wpos()
-  local apos, spos = #actargs, secpos
+  local lpos, apos, spos = #actlist, #actargs, secpos
 
 
   local ok, err
   local ok, err
   for t in gmatch(template, "[^|]+") do
   for t in gmatch(template, "[^|]+") do
     ok, err = pcall(parse_template, params, t, nparams, pos)
     ok, err = pcall(parse_template, params, t, nparams, pos)
     if ok then return end
     if ok then return end
     secpos = spos
     secpos = spos
+    actlist[lpos+1] = nil
+    actlist[lpos+2] = nil
+    actlist[lpos+3] = nil
     actargs[apos+1] = nil
     actargs[apos+1] = nil
     actargs[apos+2] = nil
     actargs[apos+2] = nil
     actargs[apos+3] = nil
     actargs[apos+3] = nil