commit - 9b4c94f07693bf4d51126899cbecf7ca5b3d904e
commit + 0d8d680e5d37cebe6ad59eb5ddb386ed9198507e
blob - 1133285b38617bb7472f5063ad4ee08c6cd06f2c
blob + c13e3c987375f4d827f999dae8a63de533fce3b5
--- tools/6c
+++ tools/6c
return result
end
+
+function bitval(b)
+ local dig = b:sub(3)
+ local len = #dig
+ local result = 0
+
+ for i = 1, len do
+ local b = dig:sub(i, i)
+
+ result = result + b * (2 ^ (len - i))
+ end
+
+ return result
+end
-----------------------------------------------------------------------
-- Checking arguments and setting read and write file
-----------------------------------------------------------------------
blob - 116e3a97da138a8770841c72c42d761751f72500
blob + 7ec0dac0f81122dc109dd6e9660fda89a89e952c
--- tools/6l
+++ tools/6l
return result
end
+
+function bitval(b)
+ local dig = b:sub(3)
+ local len = #dig
+ local result = 0
+
+ for i = 1, len do
+ local b = dig:sub(i, i)
+
+ result = result + b * (2 ^ (len - i))
+ end
+
+ return result
+end
-----------------------------------------------------------------------
-- Checking arguments
-----------------------------------------------------------------------
local ASM_INSTRUCTION = 2
local ASM_R8 = 3
local ASM_IMM8 = 4
+local ASM_MEM8 = 5
local function operlyze(op, ret)
if isregs8(op) == true then
ret.opcount = 1
table.insert(ret.details, ASM_R8)
+ table.insert(ret.operands, op)
elseif op.type == tk_type.integer then
ret.opcount = 1
local val = intval(op.raw)
+ table.insert(ret.operands, op)
if val < 256 then
table.insert(ret.details, ASM_IMM8)
elseif op.type == tk_type.hexadecimal then
ret.opcount = 1
local val = hexval(op.raw)
+ table.insert(ret.operands, op)
if val < 256 then
table.insert(ret.details, ASM_IMM8)
+ table.insert(ret.operands, op)
else
perror("operand 1 of instruction on line " .. op.line .. " is too big!")
end
local ret = {
type = ASM_INSTRUCTION,
opcount = 0,
- details = { }
+ details = { },
+ operands = { }
}
local op1 = readhdr()
local com = readhdr()
if com.type == tk_type["\n"] then
+ ret.opcount = 1
return ret
end
operlyze(op2, ret)
if ret.opcount == 0 then
+ ret.opcount = 2
return ret
end
return ret
end
- if com.type ~= tk_type[","] then
- perror("missing comma next to second operand on line " .. op1.line)
- end
+ perror("can only take up to 2 operands instructions. Line " .. first.line)
- local op3 = readhdr()
- operlyze(op3, ret)
-
- if ret.opcount == 0 then
- return ret
- end
-
- local nl = readhdr()
- if nl.type == tk_type["\n"] then
- return ret
- end
-
- perror("can only take up to 3 operands instructions. Line " .. first.line)
-
else
if first.type == tk_type.id then
local col = readhdr()
end
end
+local function instvaluate(inst)
+ local regmap = {
+ ["al"] = "000", ["ah"] = "100", ["bl"] = "011", ["bh"] = "111",
+ ["cl"] = "001", ["ch"] = "101", ["dl"] = "010", ["dh"] = "110"
+ }
+
+ local ret = {
+ modrm = nil,
+ sib = nil
+ }
+
+ local opcount = #inst.details
+
+ if opcount == 0 then
+ return ret
+ elseif opcount == 1 then
+ -- amslyze caps it at 2
+ else
+ if inst.details[1] == ASM_R8 and inst.details[2] == ASM_R8 then
+ local dstmap = regmap[gettokenkey(inst.operands[1])]
+ local srcmap = regmap[gettokenkey(inst.operands[2])]
+ ret.modrm = bitval("0b11" .. srcmap .. dstmap)
+
+ return ret
+ elseif inst.details[1] == ASM_R8 and inst.details[2] == ASM_IMM8 then
+ local dstmap = regmap[gettokenkey(inst.operands[1])]
+ ret.modrm = bitval("0b11" .. "000" .. dstmap)
+
+ return ret
+ end
+ end
+
+ return nil
+end
+
+local function writemov(inst, eval)
+ local opcount = #inst.details
+
+ if opcount ~= 2 then
+ perror("mov takes 2 operands. Line " .. inst.operands[1].line)
+ end
+
+ if inst.details[1] == ASM_R8 and inst.details[2] == ASM_R8 then
+ writeu8(dst, hexval("0h88"))
+ writeu8(dst, eval.modrm)
+ elseif inst.details[1] == ASM_R8 and inst.details[2] == ASM_IMM8 then
+ local ib = 0
+ if inst.operands[2].type == tk_type.hexadecimal then
+ ib = hexval(inst.operands[2].raw)
+ elseif inst.operands[2].type == tk_type.integer then
+ ib = intval(inst.operands[2].raw)
+ else
+ perror("attempt to mov a non integer at line " .. inst.operands[2].line)
+ end
+
+ writeu8(dst, hexval("0hC6"))
+ writeu8(dst, eval.modrm)
+ writeu8(dst, ib)
+ end
+end
+
-----------------------------------------------------------------------
-- 1st pass (syntax check and symbol table)
-----------------------------------------------------------------------
+local begin = src:seek("cur")
while true do
local hdr = readhdr()
if hdr == nil then
-----------------------------------------------------------------------
-- 2nd pass binary generation
-----------------------------------------------------------------------
+src:seek("set", begin)
+parser.inasm = false
+parser.insec = false
+while true do
+ local hdr = readhdr()
+ if hdr == nil then
+ break
+ end
+
+ if parser.inasm == true then
+ if hdr.type == tk_type["asm"] then
+ perror("illegal nested asm keyword at line " .. hdr.line .. " column " .. hdr.col)
+ elseif hdr.type == tk_type["}"] then
+ parser.inasm = false
+ else
+ if hdr.type ~= tk_type["\n"] then
+ local inst = asmlyze(hdr)
+ if inst.type == ASM_INSTRUCTION then
+ local eval = instvaluate(inst)
+
+ if eval == nil then
+ perror("unknown instruction at line " .. hdr.line)
+ end
+
+ if hdr.type == tk_type["mov"] then
+ writemov(inst, eval)
+
+ elseif hdr.type == tk_type["ret"] then
+ writeu8(dst, hexval("0hC3")) -- Only near return
+
+ elseif hdr.type == tk_type["hlt"] then
+ writeu8(dst, hexval("0hF4"))
+
+ elseif hdr.type == tk_type["cli"] then
+ writeu8(dst, hexval("0hFA"))
+ end
+ end
+ end
+ end
+ else
+ if hdr.type == tk_type["asm"] then
+ parser.inasm = true
+ readhdr() -- Skip `{`
+ end
+ end
+end
+
-----------------------------------------------------------------------
-- Closing files
-----------------------------------------------------------------------
blob - 846d2fda3cde69a0ef32cbed3930c60c8c5bb3da
blob + 520f91818c130587e79bd18473207a8f1a9b13b7
--- tools/boot.sc
+++ tools/boot.sc
asm {
_start:
- mov al, 0h10
- mov ah, 22
+ mov al, ah
+ mov ah, 0hff
ret
main:
hlt
blob - 4fd03b00959bb3a8a3763042c0eddde8adaa01e0
blob + fad84b294e1de4a24ef667ced168e53218a52de1
--- tools/linker.lua
+++ tools/linker.lua
local ASM_INSTRUCTION = 2
local ASM_R8 = 3
local ASM_IMM8 = 4
+local ASM_MEM8 = 5
local function operlyze(op, ret)
if isregs8(op) == true then
ret.opcount = 1
table.insert(ret.details, ASM_R8)
+ table.insert(ret.operands, op)
elseif op.type == tk_type.integer then
ret.opcount = 1
local val = intval(op.raw)
+ table.insert(ret.operands, op)
if val < 256 then
table.insert(ret.details, ASM_IMM8)
elseif op.type == tk_type.hexadecimal then
ret.opcount = 1
local val = hexval(op.raw)
+ table.insert(ret.operands, op)
if val < 256 then
table.insert(ret.details, ASM_IMM8)
+ table.insert(ret.operands, op)
else
perror("operand 1 of instruction on line " .. op.line .. " is too big!")
end
local ret = {
type = ASM_INSTRUCTION,
opcount = 0,
- details = { }
+ details = { },
+ operands = { }
}
local op1 = readhdr()
local com = readhdr()
if com.type == tk_type["\n"] then
+ ret.opcount = 1
return ret
end
operlyze(op2, ret)
if ret.opcount == 0 then
+ ret.opcount = 2
return ret
end
return ret
end
- if com.type ~= tk_type[","] then
- perror("missing comma next to second operand on line " .. op1.line)
- end
+ perror("can only take up to 2 operands instructions. Line " .. first.line)
- local op3 = readhdr()
- operlyze(op3, ret)
-
- if ret.opcount == 0 then
- return ret
- end
-
- local nl = readhdr()
- if nl.type == tk_type["\n"] then
- return ret
- end
-
- perror("can only take up to 3 operands instructions. Line " .. first.line)
-
else
if first.type == tk_type.id then
local col = readhdr()
end
end
+-- formats instruction to be ready for opcode generation
+local function instvaluate(inst)
+ local regmap = {
+ ["al"] = "000", ["ah"] = "100", ["bl"] = "011", ["bh"] = "111",
+ ["cl"] = "001", ["ch"] = "101", ["dl"] = "010", ["dh"] = "110"
+ }
+
+ local ret = {
+ modrm = nil,
+ sib = nil
+ }
+
+ local opcount = #inst.details
+
+ if opcount == 0 then
+ return ret
+ elseif opcount == 1 then
+ -- amslyze caps it at 2
+ else
+ if inst.details[1] == ASM_R8 and inst.details[2] == ASM_R8 then
+ local dstmap = regmap[gettokenkey(inst.operands[1])]
+ local srcmap = regmap[gettokenkey(inst.operands[2])]
+ ret.modrm = bitval("0b11" .. srcmap .. dstmap)
+
+ return ret
+ elseif inst.details[1] == ASM_R8 and inst.details[2] == ASM_IMM8 then
+ local dstmap = regmap[gettokenkey(inst.operands[1])]
+ ret.modrm = bitval("0b11" .. "000" .. dstmap)
+
+ return ret
+ end
+ end
+
+ return nil
+end
+
+local function writemov(inst, eval)
+ local opcount = #inst.details
+
+ if opcount ~= 2 then
+ perror("mov takes 2 operands. Line " .. inst.operands[1].line)
+ end
+
+ if inst.details[1] == ASM_R8 and inst.details[2] == ASM_R8 then
+ writeu8(dst, hexval("0h88"))
+ writeu8(dst, eval.modrm)
+ elseif inst.details[1] == ASM_R8 and inst.details[2] == ASM_IMM8 then
+ local ib = 0
+ if inst.operands[2].type == tk_type.hexadecimal then
+ ib = hexval(inst.operands[2].raw)
+ elseif inst.operands[2].type == tk_type.integer then
+ ib = intval(inst.operands[2].raw)
+ else
+ perror("attempt to mov a non integer at line " .. inst.operands[2].line)
+ end
+
+ writeu8(dst, hexval("0hC6"))
+ writeu8(dst, eval.modrm)
+ writeu8(dst, ib)
+ end
+end
+
-----------------------------------------------------------------------
-- 1st pass (syntax check and symbol table)
-----------------------------------------------------------------------
+local begin = src:seek("cur")
while true do
local hdr = readhdr()
if hdr == nil then
-----------------------------------------------------------------------
-- 2nd pass binary generation
-----------------------------------------------------------------------
+src:seek("set", begin)
+parser.inasm = false
+parser.insec = false
+while true do
+ local hdr = readhdr()
+ if hdr == nil then
+ break
+ end
+
+ if parser.inasm == true then
+ if hdr.type == tk_type["asm"] then
+ perror("illegal nested asm keyword at line " .. hdr.line .. " column " .. hdr.col)
+ elseif hdr.type == tk_type["}"] then
+ parser.inasm = false
+ else
+ if hdr.type ~= tk_type["\n"] then
+ local inst = asmlyze(hdr)
+ if inst.type == ASM_INSTRUCTION then
+ local eval = instvaluate(inst)
+
+ if eval == nil then
+ perror("unknown instruction at line " .. hdr.line)
+ end
+
+ if hdr.type == tk_type["mov"] then
+ writemov(inst, eval)
+
+ elseif hdr.type == tk_type["ret"] then
+ writeu8(dst, hexval("0hC3")) -- Only near return
+
+ elseif hdr.type == tk_type["hlt"] then
+ writeu8(dst, hexval("0hF4"))
+
+ elseif hdr.type == tk_type["cli"] then
+ writeu8(dst, hexval("0hFA"))
+ end
+ end
+ end
+ end
+ else
+ if hdr.type == tk_type["asm"] then
+ parser.inasm = true
+ readhdr() -- Skip `{`
+ end
+ end
+end
+
-----------------------------------------------------------------------
-- Closing files
-----------------------------------------------------------------------
blob - cc7115c9a8b1920867e53e25cd21892a6d296e45
blob + bc25e9dd9309e97d87e1e27f7aad8fb16c655a3b
--- tools/util.lua
+++ tools/util.lua
return result
end
+
+function bitval(b)
+ local dig = b:sub(3)
+ local len = #dig
+ local result = 0
+
+ for i = 1, len do
+ local b = dig:sub(i, i)
+
+ result = result + b * (2 ^ (len - i))
+ end
+
+ return result
+end