~charles/awk-riscv

1239206ecf5cb343104988cb33c37b5f3e3a7728 — Charles Daniels 10 months ago 3e3a9d0
assemble branches
2 files changed, 113 insertions(+), 4 deletions(-)

M riscv.awk
A tests/simulation/asm_branch.txt
M riscv.awk => riscv.awk +79 -4
@@ 234,6 234,9 @@
# on is quite limited. In general, if you feed this program garbage, it will
# probably behave in unpredictable and undesirable ways.
#
# The assembler does not detect or mitigate jumps to labels outside of the
# maximum range of branch or jump instructions.
#
###############################################################################




@@ 370,6 373,14 @@ function packJimm(v) {
	       lshift(and(v, 0x100000), 11))
}

function packBimm(v) {
	return or( \
		lshift(and(v, 0x1000), 19), \
		lshift(and(v, 0x7e0), 20), \
		lshift(and(v, 0x1e), 7), \
		rshift(and(v, 0x800), 4))
}

#### INSTRUCTION DECODING #####################################################

# masks to pull relevant values out of an instruction


@@ 603,6 614,8 @@ function assemble() {
	# R -- normal register-register instructions
	#
	# nop -- generate a no-op
	#
	# B -- branches
	asm_style = "error"

	if (tolower($1) == "addi") {


@@ 737,6 750,34 @@ function assemble() {
		asm_style = "I"
		asm_opcode = 0x67

	} else if  (tolower($1) == "beq") {
		asm_style = "B"
		asm_opcode = 0x63

	} else if  (tolower($1) == "bne") {
		asm_style = "B"
		asm_opcode = 0x63
		asm_funct3 = 0x1

	} else if  (tolower($1) == "blt") {
		asm_style = "B"
		asm_opcode = 0x63
		asm_funct3 = 0x4

	} else if  (tolower($1) == "bltu") {
		asm_style = "B"
		asm_opcode = 0x63
		asm_funct3 = 0x6

	} else if  (tolower($1) == "bge") {
		asm_style = "B"
		asm_opcode = 0x63
		asm_funct3 = 0x5

	} else if  (tolower($1) == "bgeu") {
		asm_style = "B"
		asm_opcode = 0x63
		asm_funct3 = 0x7

	} else {
		printf("# ASSEMBLER ERROR: expected opcode, got '%s' (line %d: '%s')\n", $1, NR, asm_line)


@@ 763,7 804,7 @@ function assemble() {
			assemble_errors++
			return
		}
		asm_immI = dec2two($4)
		asm_immI = dec2two(strtonum($4))

	} else if (asm_style == "shift") {
		asm_rd = parsereg($2)


@@ 784,7 825,7 @@ function assemble() {
			assemble_errors++
			return
		}
		asm_immI = or(dec2two($4), lshift(asm_arith, 10))
		asm_immI = or(dec2two(strtonum($4)), lshift(asm_arith, 10))

	} else if (asm_style == "U") {
		asm_rd = parsereg($2)


@@ 821,6 862,33 @@ function assemble() {
			assemble_errors++
			return
		}

	} else if (asm_style == "B") {
		asm_rs1 = parsereg($2)
		if (asm_rs1 < 0) {
			printf("# ASSEMBLER ERROR: expected rs1 register, got '%s' (line %d: '%s')\n", $2, NR, asm_line)
			assemble_errors++
			return
		}

		asm_rs2 = parsereg($3)
		if (asm_rs1 < 0) {
			printf("# ASSEMBLER ERROR: expected rs2 register, got '%s' (line %d: '%s')\n", $3, NR, asm_line)
			assemble_errors++
			return
		}

		if (match($4, /^0x[0-9a-fA-F]{1,8}$/) || match($4, /^[0-9-]+$/)) {
			if (strtonum($4) > 4095 || strtonum($4) < -4096) {
				printf("# ASSEMBLER ERROR: expected immediate in range -4096...4095, got '%s' (line %d: '%s')\n", $4, NR, asm_line)
				assemble_errors++
				return
			}
			asm_immB = packBimm(dec2two(strtonum($4)))
		} else {
			unresolved[$4] = asmcursor
		}

	} else if (asm_style == "nop") {
		# do nothing
	}


@@ 835,7 903,8 @@ function assemble() {
		 asm_immU, \
		 lshift(asm_rs2, 20), \
		 lshift(asm_funct7, 25), \
		 asm_immJ)
		 asm_immJ, \
		 asm_immB)

	memwrite(asmcursor, asm_inst)



@@ 1088,10 1157,16 @@ $1 == "resolve" {

		if (traceresolve) {
			printf("# \tcurrent value: 0x%08x at mem[0x%08x]\n", resolve_memval, resolve_addr)
			printf("# \tpacking type: %s\n", type(resolve_memval))
			printf("# \tresolves to: 0x%08x\n", labels[resolve_label])
		}

		resolve_memval = or(resolve_memval, packJimm(dec2two(labels[resolve_label] - resolve_addr)))
		if (type(resolve_memval) == "J") {
			resolve_memval = or(resolve_memval, packJimm(dec2two(labels[resolve_label] - resolve_addr)))
		} else {
			resolve_memval = or(resolve_memval, packBimm(dec2two(labels[resolve_label] - resolve_addr)))
		}

		if (traceresolve) {
			printf("# \tupdate memory value to: 0x%08x\n", resolve_memval)
		}

A tests/simulation/asm_branch.txt => tests/simulation/asm_branch.txt +34 -0
@@ 0,0 1,34 @@
tracemem 1
traceresolve 1

mode assemble
beq x1 x2 0x1
beq x1 x2 0x2
beq x1 x2 0x4
beq x1 x2 0x8
beq x1 x2 -1
beq x1 x2 -2
beq x1 x2 -4
l1:
nop
nop
beq x1 x2 l1
beq x1 x2 l2
nop
nop
l2:


mode normal

assert mem 0x000 0x00208063
assert mem 0x004 0x00208163
assert mem 0x008 0x00208263
assert mem 0x00c 0x00208463
assert mem 0x010 0xfe208fe3
assert mem 0x014 0xfe208fe3
assert mem 0x018 0xfe208ee3

resolve

dump