Commit Diff


commit - 9b4c94f07693bf4d51126899cbecf7ca5b3d904e
commit + 0d8d680e5d37cebe6ad59eb5ddb386ed9198507e
blob - 1133285b38617bb7472f5063ad4ee08c6cd06f2c
blob + c13e3c987375f4d827f999dae8a63de533fce3b5
--- tools/6c
+++ tools/6c
@@ -221,6 +221,20 @@ function hexval(hex)
 
 	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
@@ -221,6 +221,20 @@ function hexval(hex)
 
 	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
 -----------------------------------------------------------------------
@@ -285,14 +299,17 @@ local ASM_LABEL = 1
 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)
@@ -302,9 +319,11 @@ local function operlyze(op, ret)
 	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
@@ -320,7 +339,8 @@ local function asmlyze(first)
 		local ret = { 
 			type = ASM_INSTRUCTION,
 			opcount = 0,
-			details = { }
+			details = { },
+			operands = { }
 		}
 
 		local op1 = readhdr()
@@ -333,6 +353,7 @@ local function asmlyze(first)
 		local com = readhdr()
 
 		if com.type == tk_type["\n"] then
+			ret.opcount = 1
 			return ret
 		end
 
@@ -344,6 +365,7 @@ local function asmlyze(first)
 		operlyze(op2, ret)
 
 		if ret.opcount == 0 then
+			ret.opcount = 2
 			return ret
 		end
 
@@ -352,24 +374,8 @@ local function asmlyze(first)
 			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()
@@ -385,9 +391,71 @@ local function asmlyze(first)
 	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
@@ -440,7 +508,54 @@ end
 -----------------------------------------------------------------------
 -- 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
@@ -1,7 +1,7 @@
 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
@@ -62,14 +62,17 @@ local ASM_LABEL = 1
 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)
@@ -79,9 +82,11 @@ local function operlyze(op, ret)
 	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
@@ -97,7 +102,8 @@ local function asmlyze(first)
 		local ret = { 
 			type = ASM_INSTRUCTION,
 			opcount = 0,
-			details = { }
+			details = { },
+			operands = { }
 		}
 
 		local op1 = readhdr()
@@ -110,6 +116,7 @@ local function asmlyze(first)
 		local com = readhdr()
 
 		if com.type == tk_type["\n"] then
+			ret.opcount = 1
 			return ret
 		end
 
@@ -121,6 +128,7 @@ local function asmlyze(first)
 		operlyze(op2, ret)
 
 		if ret.opcount == 0 then
+			ret.opcount = 2
 			return ret
 		end
 
@@ -129,24 +137,8 @@ local function asmlyze(first)
 			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()
@@ -162,9 +154,72 @@ local function asmlyze(first)
 	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
@@ -217,7 +272,54 @@ end
 -----------------------------------------------------------------------
 -- 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
@@ -219,3 +219,17 @@ function hexval(hex)
 
 	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