re-worked assemlber to load from file and have real labels

master
bx 2021-09-01 22:05:19 +01:00
parent 943f45dcc3
commit 2810109764
3 changed files with 272 additions and 246 deletions

View File

@ -1,27 +1,5 @@
$bytes = [] # assembler.rb
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
# # # REGISTER NAMES # # # # # # REGISTER NAMES # # #
def r0() 0 end # zero def r0() 0 end # zero
@ -57,6 +35,71 @@ def sp() 29 end # stack pointer
def fp() 30 end # frame pointer def fp() 30 end # frame pointer
def ra() 31 end # return address 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 # # # # # # INSTRUCTIONS # # #
@ -150,8 +193,6 @@ def jr(reg)
word op word op
end end
# # # PSEUDO-INSTRUCTIONS # # # # # # PSEUDO-INSTRUCTIONS # # #
def nop def nop
word 0x00000000 word 0x00000000
@ -163,138 +204,27 @@ def lwi(val, dest)
ori dest, val, dest ori dest, val, dest
end end
def label
return $bytes.length + $base_addr
end end
# this is a terrible idea and im doing it
#$labels = {}
#def method_missing(m, *args)
# puts m.to_s
# super
#end
# # # CONSTANTS # # # # # # CONSTANTS # # #
$base_addr = 0x80010000 # 0x10000 # 0x80010000 base_addr = 0x80010000 # 0x10000 # 0x80010000
$file_size = 0x800 * 3 file_size = 0x800 * 3
$gp0 = 0x1F801810
$gp1 = 0x1F801814
# # # EXE HEADER # # # f = File.new "exe-header.asm.rb", "r"
string "PS-X EXE" exe_header = Assembler.new(base_addr, 0x800).assemble f.read
zero_fill 0x00f f.close
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 "main.asm.rb", "r"
binary = Assembler.new(base_addr, file_size).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 "LOADTHIS.EXE", "wb" f = File.new "LOADTHIS.EXE", "wb"
f.write $exe_header.pack("C*") f.write exe_header.pack("C*")
f.write $bytes.pack("C*") f.write binary.pack("C*")
f.close f.close

18
exe-header.asm.rb 100644
View 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 100644
View 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