re-worked assemlber to load from file and have real labels
This commit is contained in:
		
							parent
							
								
									943f45dcc3
								
							
						
					
					
						commit
						2810109764
					
				
							
								
								
									
										222
									
								
								assembler.rb
									
									
									
									
									
								
							
							
						
						
									
										222
									
								
								assembler.rb
									
									
									
									
									
								
							| @ -1,27 +1,5 @@ | ||||
| 
 | ||||
| $bytes = [] | ||||
| 
 | ||||
| def zero_fill(pos) | ||||
| 	while ($bytes.length <= pos) do | ||||
| 		$bytes.push(0) | ||||
| 	end | ||||
| end | ||||
| 
 | ||||
| def word(i) | ||||
| 	$bytes.push((i & 0x000000ff), | ||||
| 		(i & 0x0000ff00) >> 8, | ||||
| 		(i & 0x00ff0000) >> 16, | ||||
| 		(i & 0xff000000) >> 24) | ||||
| end | ||||
| 
 | ||||
| def string(s) | ||||
| 	$bytes.push *s.bytes | ||||
| 	$bytes.push 0 # null terminate | ||||
| 	while (($bytes.length % 4) != 0) do | ||||
| 		$bytes.push 0 | ||||
| 	end | ||||
| end | ||||
| 
 | ||||
| # assembler.rb | ||||
| 
 | ||||
| # # # REGISTER NAMES # # # | ||||
| def r0() 0 end # zero | ||||
| @ -57,6 +35,71 @@ def sp() 29 end # stack pointer | ||||
| def fp() 30 end # frame pointer | ||||
| def ra() 31 end # return address | ||||
| 
 | ||||
| class Assembler | ||||
| 	def initialize(base, size) | ||||
| 		@base_addr = base | ||||
| 		@file_size = size | ||||
| 	end | ||||
| 
 | ||||
| 	def inspect | ||||
| 		"(Assembler base_addr:0x#{@base_addr.to_s 16} file_size:0x#{@file_size.to_s 16})" | ||||
| 	end | ||||
| 
 | ||||
| 	# TODO: Sub-labels | ||||
| 
 | ||||
| 	def label(l) | ||||
| 		return if @first_pass == false | ||||
| 		raise "error redefinition of label #{l.to_s}" if @labels.member?(l.to_s) | ||||
| 		@labels[l.to_s] = @bytes.length + @base_addr | ||||
| 	end | ||||
| 
 | ||||
| 	def method_missing(m, *args, &block) | ||||
| 		return 0 if @first_pass | ||||
| 		if m.to_s[0, 2] == "l_" then | ||||
| 			return @labels[m.to_s[2..]] if @labels.member?(m.to_s[2..]) | ||||
| 			raise "label doesn't exist #{m.to_s}" | ||||
| 		else | ||||
| 			super | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	def assemble(source) | ||||
| 		@first_pass = true | ||||
| 		@labels = {} | ||||
| 		@bytes = [] | ||||
| 		binding.eval source | ||||
| 
 | ||||
| 		@first_pass = false | ||||
| 		@bytes = [] | ||||
| 		binding.eval source | ||||
| 
 | ||||
| 		puts "assembled 0x#{@bytes.length.to_s 16} (#{@bytes.length}) bytes" | ||||
| 		raise "CODE IS GREATER THAN FILESIZE" if @bytes.length > @file_size | ||||
| 		zero_fill @file_size - 1 | ||||
| 
 | ||||
| 		return @bytes | ||||
| 	end | ||||
| 
 | ||||
| 	def zero_fill(pos) | ||||
| 		while (@bytes.length <= pos) do | ||||
| 			@bytes.push(0) | ||||
| 		end | ||||
| 	end | ||||
| 	 | ||||
| 	def word(i) | ||||
| 		@bytes.push((i & 0x000000ff), | ||||
| 			(i & 0x0000ff00) >> 8, | ||||
| 			(i & 0x00ff0000) >> 16, | ||||
| 			(i & 0xff000000) >> 24) | ||||
| 	end | ||||
| 	 | ||||
| 	def string(s) | ||||
| 		@bytes.push *s.bytes | ||||
| 		@bytes.push 0 # null terminate | ||||
| 		while ((@bytes.length % 4) != 0) do | ||||
| 			@bytes.push 0 | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 
 | ||||
| 	# # # INSTRUCTIONS # # # | ||||
| @ -150,8 +193,6 @@ def jr(reg) | ||||
| 		word op | ||||
| 	end | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 	# # # PSEUDO-INSTRUCTIONS # # # | ||||
| 	def nop | ||||
| 		word 0x00000000 | ||||
| @ -163,138 +204,27 @@ def lwi(val, dest) | ||||
| 		ori dest, val, dest | ||||
| 	end | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| def label | ||||
| 	return $bytes.length + $base_addr | ||||
| end | ||||
| 
 | ||||
| # this is a terrible idea and im doing it | ||||
| #$labels = {} | ||||
| #def method_missing(m, *args) | ||||
| #	puts m.to_s | ||||
| #	super | ||||
| #end | ||||
| 
 | ||||
| 
 | ||||
| # # # CONSTANTS # # # | ||||
| $base_addr = 0x80010000 # 0x10000 # 0x80010000 | ||||
| $file_size = 0x800 * 3 | ||||
| $gp0 = 0x1F801810 | ||||
| $gp1 = 0x1F801814 | ||||
| base_addr = 0x80010000 # 0x10000 # 0x80010000 | ||||
| file_size = 0x800 * 3 | ||||
| 
 | ||||
| # # # EXE HEADER # # # | ||||
| string "PS-X EXE" | ||||
| zero_fill 0x00f | ||||
| word $base_addr # initial pc | ||||
| word 0x00000000 # initial GP/R28 | ||||
| word $base_addr # destintation address in RAM | ||||
| word $file_size # file size excluding header (must be N * 0x800) | ||||
| word 0x00000000 # Unknown/Unused | ||||
| word 0x00000000 # Unknown/Unused | ||||
| word 0x00000000 # Memfill start address | ||||
| word 0x00000000 # Memfill size in bytes | ||||
| word 0x801ffff0 # Initial SP/R29 & FP/R30 Base | ||||
| word 0x00000000 # Initial SP/R29 & FP/R30 Offs | ||||
| zero_fill 0x4b # Reserved for A(43h) Function | ||||
| # Ascii marker would go here | ||||
| zero_fill 0x7ff | ||||
| $exe_header = $bytes[0..] | ||||
| $bytes = [] | ||||
| f = File.new "exe-header.asm.rb", "r" | ||||
| exe_header = Assembler.new(base_addr, 0x800).assemble f.read | ||||
| f.close | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| # # # PROGRAM CODE # # # | ||||
| nop | ||||
| jmp $base_addr + 0x400 | ||||
| nop | ||||
| 
 | ||||
| l_hello_world = label | ||||
| string "ello wrld!\n" | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| l_printf = label | ||||
| addiu r0, 0xa0, at # address of bios func | ||||
| jr at | ||||
| addiu r0, 0x3f, t1 # printf number | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| zero_fill 0x400 - 1 | ||||
| nop | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| lwi l_hello_world, a0 | ||||
| jal l_printf | ||||
| addiu sp, -16, sp # delay slot | ||||
| addiu sp, 16, sp | ||||
| 
 | ||||
| nop ; nop ; nop ; nop | ||||
| 
 | ||||
| 
 | ||||
| # THIS IS NEEDED | ||||
| lwi $gp1, t0 | ||||
| lwi 0x03_00_00_00, t1 # display enable | ||||
| sw t1, 0, t0 | ||||
| 
 | ||||
| lwi $gp0, t0 | ||||
| 
 | ||||
| lwi 0xe1_000000 + 0b0_0_0_1_0_01_00_0_0000, t1 | ||||
| sw t1, 0, t0 | ||||
| 
 | ||||
| # THIS IS NEEDED | ||||
| lwi 0xe4_000000 + (640) + (480 << 10), t1 # Drawing Area bottom right | ||||
| sw t1, 0, t0 | ||||
| 
 | ||||
| def line(st, en) | ||||
| 	lwi 0x40_ffffff, t1 # monochrome line, color ffffff | ||||
| 	sw t1, 0, t0 | ||||
| 
 | ||||
| 	lwi st, t1 # line vert 1 | ||||
| 	sw t1, 0, t0 | ||||
| 
 | ||||
| 	lwi en, t1 # line vert 2 | ||||
| 	sw t1, 0, t0 | ||||
| end | ||||
| 
 | ||||
| # l_end_loop = label | ||||
| line 0x0010_0010, 0x0030_0030 | ||||
| line 0x0030_0030, 0x0060_0000 | ||||
| line 0x0060_000a, 0x00f0_0060 | ||||
| 
 | ||||
| nop ; nop ; nop ; nop | ||||
| nop ; nop ; nop ; nop | ||||
| nop ; nop ; nop ; nop | ||||
| nop ; nop ; nop ; nop | ||||
| 
 | ||||
| l_end_loop = label | ||||
| nop | ||||
| lwi l_end_loop, t9 | ||||
| jr t9 | ||||
| nop | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| puts "assembled 0x#{$bytes.length.to_s 16} (#{$bytes.length}) bytes" | ||||
| raise "CODE IS GREATER THAN FILESIZE" if $bytes.length > $file_size | ||||
| zero_fill $file_size - 1 | ||||
| f = File.new "main.asm.rb", "r" | ||||
| binary = Assembler.new(base_addr, file_size).assemble f.read | ||||
| f.close | ||||
| 
 | ||||
| f = File.new "LOADTHIS.EXE", "wb" | ||||
| f.write $exe_header.pack("C*") | ||||
| f.write $bytes.pack("C*") | ||||
| f.write exe_header.pack("C*") | ||||
| f.write binary.pack("C*") | ||||
| f.close | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										18
									
								
								exe-header.asm.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								exe-header.asm.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| 
 | ||||
| # exe-header.asm.rb | ||||
| 
 | ||||
| string "PS-X EXE" | ||||
| zero_fill 0x00f | ||||
| word @base_addr # initial pc | ||||
| word 0x00000000 # initial GP/R28 | ||||
| word @base_addr # destintation address in RAM | ||||
| word @file_size # file size excluding header (must be N * 0x800) | ||||
| word 0x00000000 # Unknown/Unused | ||||
| word 0x00000000 # Unknown/Unused | ||||
| word 0x00000000 # Memfill start address | ||||
| word 0x00000000 # Memfill size in bytes | ||||
| word 0x801ffff0 # Initial SP/R29 & FP/R30 Base | ||||
| word 0x00000000 # Initial SP/R29 & FP/R30 Offs | ||||
| zero_fill 0x4b # Reserved for A(43h) Function | ||||
| # Ascii marker would go here | ||||
| zero_fill 0x7ff | ||||
							
								
								
									
										78
									
								
								main.asm.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								main.asm.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,78 @@ | ||||
| 
 | ||||
| # main.asm.rb | ||||
| 
 | ||||
| $gp0 = 0x1F801810 | ||||
| $gp1 = 0x1F801814 | ||||
| 
 | ||||
| jmp l_start | ||||
| nop | ||||
| 
 | ||||
| label :hello_world | ||||
| 	string "ello wrld!\n" | ||||
| 
 | ||||
| label :printf | ||||
| 	addiu r0, 0xa0, at # address of bios func | ||||
| 	jr at | ||||
| 	addiu r0, 0x3f, t1 # printf number | ||||
| 
 | ||||
| label :draw_line | ||||
| 	# todo: draw line function, take args in a0 - a3 | ||||
| 	# tood: implement shift left so we can use that | ||||
| 	lwi $gp0, t0 | ||||
| 
 | ||||
| 	lwi 0x40_ffffff, t1 # monochrome line, color ffffff | ||||
| 	sw t1, 0, t0 | ||||
| 
 | ||||
| 	# lwi st, t1 # line vert 1 | ||||
| 	sw t1, 0, t0 | ||||
| 
 | ||||
| 	# lwi en, t1 # line vert 2 | ||||
| 	sw t1, 0, t0 | ||||
| 
 | ||||
| label :start | ||||
| 	nop ; nop ; nop ; nop | ||||
| 
 | ||||
| 	# THIS IS NEEDED | ||||
| 	lwi $gp1, t0 | ||||
| 	lwi 0x03_00_00_00, t1 # display enable | ||||
| 	sw t1, 0, t0 | ||||
| 
 | ||||
| 	lwi $gp0, t0 | ||||
| 
 | ||||
| 	lwi 0xe1_000000 + 0b0_0_0_1_0_01_00_0_0000, t1 | ||||
| 	sw t1, 0, t0 | ||||
| 
 | ||||
| 	# THIS IS NEEDED | ||||
| 	lwi 0xe4_000000 + (640) + (480 << 10), t1 # Drawing Area bottom right | ||||
| 	sw t1, 0, t0 | ||||
| 
 | ||||
| 	def line(st, en) | ||||
| 		lwi 0x40_ffffff, t1 # monochrome line, color ffffff | ||||
| 		sw t1, 0, t0 | ||||
| 
 | ||||
| 		lwi st, t1 # line vert 1 | ||||
| 		sw t1, 0, t0 | ||||
| 
 | ||||
| 		lwi en, t1 # line vert 2 | ||||
| 		sw t1, 0, t0 | ||||
| 	end | ||||
| 
 | ||||
| 	line 0x0010_0010, 0x0030_0030 | ||||
| 	line 0x0030_0030, 0x0060_0000 | ||||
| 	line 0x0060_000a, 0x00f0_0060 | ||||
| 
 | ||||
| 	lwi l_hello_world, a0 | ||||
| 	jal l_printf | ||||
| 	addiu sp, -16, sp # delay slot | ||||
| 	addiu sp, 16, sp | ||||
| 
 | ||||
| label :end_loop | ||||
| 	lwi l_end_loop, t9 | ||||
| 	jr t9 | ||||
| 	nop | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user