PREFIX = "x\"";
|
PREFIX = "x\"";
|
SUFFIX = "\"";
|
SUFFIX = "\"";
|
SEPERATOR = ", ";
|
SEPERATOR = ", ";
|
|
|
|
|
|
|
class OpcodeByte1
|
class OpcodeByte1
|
attr_accessor :op, :register, :cond;
|
attr_accessor :op, :register, :cond;
|
def to_hex
|
def to_hex
|
s = (op << 4 | register.number << 1 | cond).to_s(16);
|
s = (op << 4 | register.number << 1 | cond).to_s(16);
|
if s.length == 1
|
if s.length == 1
|
"0"+s;
|
"0"+s;
|
elsif s.length == 0
|
elsif s.length == 0
|
"00";
|
"00";
|
else
|
else
|
s
|
s
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
class OpcodeByte2
|
class OpcodeByte2
|
attr_accessor :cond, :reg2, :useextra, :reg3;
|
attr_accessor :cond, :reg2, :useextra, :reg3;
|
def to_hex
|
def to_hex
|
s=(cond << 7 | reg2.number << 4 | useextra << 3 | reg3.number).to_s(16);
|
s=(cond << 7 | reg2.number << 4 | useextra << 3 | reg3.number).to_s(16);
|
if s.length == 1
|
if s.length == 1
|
"0"+s;
|
"0"+s;
|
elsif s.length==0
|
elsif s.length==0
|
"00";
|
"00";
|
else
|
else
|
s;
|
s;
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
|
|
class Register8
|
class Register8
|
attr_accessor :number
|
attr_accessor :number
|
def initialize(num)
|
def initialize(num)
|
@number=num
|
@number=num
|
end
|
end
|
end
|
end
|
class OpcodeOption
|
class OpcodeOption
|
attr_accessor :number
|
attr_accessor :number
|
def initialize(num)
|
def initialize(num)
|
@number=num;
|
@number=num;
|
end
|
end
|
end
|
end
|
|
|
$iftr = 0; #0 for no condition, 1 for if TR, 2 for if not TR
|
$iftr = 0; #0 for no condition, 1 for if TR, 2 for if not TR
|
$useextra = 0;
|
$useextra = 0;
|
$position = 0;
|
$position = 0;
|
|
|
def set_cond(o1, o2)
|
def set_cond(o1, o2)
|
if $iftr==0 then
|
if $iftr==0 then
|
o1.cond=0;
|
o1.cond=0;
|
o2.cond=0;
|
o2.cond=0;
|
elsif $iftr==1 then
|
elsif $iftr==1 then
|
o1.cond=1;
|
o1.cond=1;
|
o2.cond=0;
|
o2.cond=0;
|
else
|
else
|
o1.cond=0;
|
o1.cond=0;
|
o2.cond=1;
|
o2.cond=1;
|
end
|
end
|
end
|
end
|
def output_op(value)
|
def output_op(value)
|
printf PREFIX + value + SUFFIX;
|
printf PREFIX + value + SUFFIX;
|
printf SEPERATOR;
|
printf SEPERATOR;
|
$position+=2;
|
$position+=2;
|
end
|
end
|
|
|
|
|
def mov_r8_imm8(reg,imm)
|
def mov_r8_imm8(reg,imm)
|
o = OpcodeByte1.new();
|
o = OpcodeByte1.new();
|
o.op = 0;
|
o.op = 0;
|
o.register=reg;
|
o.register=reg;
|
if $iftr<2 then
|
if $iftr<2 then
|
o.cond=$iftr;
|
o.cond=$iftr;
|
else
|
else
|
raise "if_tr_notset is not allowed with this opcode";
|
raise "if_tr_notset is not allowed with this opcode";
|
end
|
end
|
output_op(o.to_hex.rjust(2,"0") + imm.to_s(16).rjust(2,"0"))
|
output_op(o.to_hex.rjust(2,"0") + imm.to_s(16).rjust(2,"0"))
|
end
|
end
|
def mov_rm8_imm8(reg,imm)
|
def mov_rm8_imm8(reg,imm)
|
o=OpcodeByte1.new();
|
o=OpcodeByte1.new();
|
o.op=1;
|
o.op=1;
|
o.register=reg;
|
o.register=reg;
|
if $iftr<2 then
|
if $iftr<2 then
|
o.cond=$iftr;
|
o.cond=$iftr;
|
else
|
else
|
raise "if_tr_notset is not allowed with this opcode";
|
raise "if_tr_notset is not allowed with this opcode";
|
end
|
end
|
output_op(o.to_hex.rjust(2,"0") + imm.to_s(16).rjust(2,"0"));
|
output_op(o.to_hex.rjust(2,"0") + imm.to_s(16).rjust(2,"0"));
|
end
|
end
|
|
|
def do_group_reg_reg(opcode,group,reg1,reg2)
|
def do_group_reg_reg(opcode,group,reg1,reg2)
|
o1 = OpcodeByte1.new()
|
o1 = OpcodeByte1.new()
|
o1.op=opcode;
|
o1.op=opcode;
|
o1.register=reg1;
|
o1.register=reg1;
|
o2 = OpcodeByte2.new()
|
o2 = OpcodeByte2.new()
|
o2.useextra=$useextra;
|
o2.useextra=$useextra;
|
o2.reg2=reg2;
|
o2.reg2=reg2;
|
o2.reg3=OpcodeOption.new(group); #opcode group
|
o2.reg3=OpcodeOption.new(group); #opcode group
|
set_cond(o1,o2)
|
set_cond(o1,o2)
|
output_op(o1.to_hex.rjust(2,"0") + o2.to_hex.rjust(2,"0"))
|
output_op(o1.to_hex.rjust(2,"0") + o2.to_hex.rjust(2,"0"))
|
end
|
end
|
def do_subgroup_reg(opcode,group,subgroup,reg1)
|
def do_subgroup_reg(opcode,group,subgroup,reg1)
|
o1 = OpcodeByte1.new()
|
o1 = OpcodeByte1.new()
|
o1.op=opcode;
|
o1.op=opcode;
|
o1.register=reg1;
|
o1.register=reg1;
|
o2 = OpcodeByte2.new()
|
o2 = OpcodeByte2.new()
|
o2.useextra=$useextra;
|
o2.useextra=$useextra;
|
o2.reg2=OpcodeOption.new(subgroup);
|
o2.reg2=OpcodeOption.new(subgroup);
|
o2.reg3=OpcodeOption.new(group); #opcode group
|
o2.reg3=OpcodeOption.new(group); #opcode group
|
set_cond(o1,o2)
|
set_cond(o1,o2)
|
output_op(o1.to_hex.rjust(2,"0") + o2.to_hex.rjust(2,"0"))
|
output_op(o1.to_hex.rjust(2,"0") + o2.to_hex.rjust(2,"0"))
|
end
|
end
|
|
|
def and_reg_reg(reg1, reg2)
|
def and_reg_reg(reg1, reg2)
|
do_group_reg_reg(4,0,reg1,reg2)
|
do_group_reg_reg(4,0,reg1,reg2)
|
end;
|
end;
|
def or_reg_reg(reg1, reg2)
|
def or_reg_reg(reg1, reg2)
|
do_group_reg_reg(4,1,reg1,reg2)
|
do_group_reg_reg(4,1,reg1,reg2)
|
end;
|
end;
|
def xor_reg_reg(reg1, reg2)
|
def xor_reg_reg(reg1, reg2)
|
do_group_reg_reg(4,2,reg1,reg2)
|
do_group_reg_reg(4,2,reg1,reg2)
|
end;
|
end;
|
def not_reg_reg(reg1, reg2)
|
def not_reg_reg(reg1, reg2)
|
do_group_reg_reg(4,3,reg1,reg2)
|
do_group_reg_reg(4,3,reg1,reg2)
|
end;
|
end;
|
def lsh_reg_reg(reg1, reg2)
|
def lsh_reg_reg(reg1, reg2)
|
do_group_reg_reg(4,4,reg1,reg2)
|
do_group_reg_reg(4,4,reg1,reg2)
|
end;
|
end;
|
def rsh_reg_reg(reg1, reg2)
|
def rsh_reg_reg(reg1, reg2)
|
do_group_reg_reg(4,5,reg1,reg2)
|
do_group_reg_reg(4,5,reg1,reg2)
|
end;
|
end;
|
def lro_reg_reg(reg1, reg2)
|
def lro_reg_reg(reg1, reg2)
|
do_group_reg_reg(4,6,reg1,reg2)
|
do_group_reg_reg(4,6,reg1,reg2)
|
end;
|
end;
|
def rro_reg_reg(reg1, reg2)
|
def rro_reg_reg(reg1, reg2)
|
do_group_reg_reg(4,7,reg1,reg2)
|
do_group_reg_reg(4,7,reg1,reg2)
|
end;
|
end;
|
#comparisons
|
#comparisons
|
def cmpgt_reg_reg(reg1, reg2)
|
def cmpgt_reg_reg(reg1, reg2)
|
do_group_reg_reg(3,0,reg1,reg2)
|
do_group_reg_reg(3,0,reg1,reg2)
|
end;
|
end;
|
def cmpgte_reg_reg(reg1, reg2)
|
def cmpgte_reg_reg(reg1, reg2)
|
do_group_reg_reg(3,1,reg1,reg2)
|
do_group_reg_reg(3,1,reg1,reg2)
|
end;
|
end;
|
def cmplt_reg_reg(reg1, reg2)
|
def cmplt_reg_reg(reg1, reg2)
|
do_group_reg_reg(3,2,reg1,reg2)
|
do_group_reg_reg(3,2,reg1,reg2)
|
end;
|
end;
|
def cmplte_reg_reg(reg1, reg2)
|
def cmplte_reg_reg(reg1, reg2)
|
do_group_reg_reg(3,3,reg1,reg2)
|
do_group_reg_reg(3,3,reg1,reg2)
|
end;
|
end;
|
def cmpeq_reg_reg(reg1, reg2)
|
def cmpeq_reg_reg(reg1, reg2)
|
do_group_reg_reg(3,4,reg1,reg2)
|
do_group_reg_reg(3,4,reg1,reg2)
|
end;
|
end;
|
def cmpneq_reg_reg(reg1, reg2)
|
def cmpneq_reg_reg(reg1, reg2)
|
do_group_reg_reg(3,5,reg1,reg2)
|
do_group_reg_reg(3,5,reg1,reg2)
|
end;
|
end;
|
def cmpeq_reg_0(reg1)
|
def cmpeq_reg_0(reg1)
|
do_group_reg_reg(3,6,reg1,Register8.new(0)) #last arg isn't used
|
do_group_reg_reg(3,6,reg1,Register8.new(0)) #last arg isn't used
|
end;
|
end;
|
def cmpneq_reg_0(reg1)
|
def cmpneq_reg_0(reg1)
|
do_group_reg_reg(3,7,reg1,Register8.new(0))
|
do_group_reg_reg(3,7,reg1,Register8.new(0))
|
end;
|
end;
|
|
|
def mov_reg_mreg(reg1, reg2)
|
def mov_reg_mreg(reg1, reg2)
|
do_group_reg_reg(5,2,reg1,reg2)
|
do_group_reg_reg(5,2,reg1,reg2)
|
end
|
end
|
def mov_mreg_reg(reg1, reg2)
|
def mov_mreg_reg(reg1, reg2)
|
do_group_reg_reg(5,3,reg1,reg2)
|
do_group_reg_reg(5,3,reg1,reg2)
|
end
|
end
|
def mov_reg_reg(reg1, reg2)
|
def mov_reg_reg(reg1, reg2)
|
do_group_reg_reg(5,1,reg1,reg2)
|
do_group_reg_reg(5,1,reg1,reg2)
|
end
|
end
|
|
|
|
|
|
|
def mov(arg1,arg2)
|
def mov(arg1,arg2)
|
if arg1.kind_of? Register8 and arg2.kind_of? Integer and arg2<0x100 then
|
if arg1.kind_of? Register8 and arg2.kind_of? Integer and arg2<0x100 then
|
mov_r8_imm8 arg1,arg2
|
mov_r8_imm8 arg1,arg2
|
elsif arg1.kind_of? Array and arg2.kind_of? Integer and arg2<0x100 then
|
elsif arg1.kind_of? Array and arg2.kind_of? Integer and arg2<0x100 then
|
if arg1.length>1 or arg1.length<1 or not arg1[0].kind_of? Register8 then
|
if arg1.length>1 or arg1.length<1 or not arg1[0].kind_of? Register8 then
|
raise "memory reference is not correct. Only a register is allowed";
|
raise "memory reference is not correct. Only a register is allowed";
|
end
|
end
|
reg=arg1[0];
|
reg=arg1[0];
|
mov_rm8_imm8 reg, arg2
|
mov_rm8_imm8 reg, arg2
|
elsif arg1.kind_of? Array and arg2.kind_of? Register8 then
|
elsif arg1.kind_of? Array and arg2.kind_of? Register8 then
|
if arg1.length>1 or arg1.length<1 or not arg1[0].kind_of? Register8 then
|
if arg1.length>1 or arg1.length<1 or not arg1[0].kind_of? Register8 then
|
raise "memory reference is not correct. Only a register is allowed";
|
raise "memory reference is not correct. Only a register is allowed";
|
end
|
end
|
mov_mreg_reg arg1[0], arg2
|
mov_mreg_reg arg1[0], arg2
|
elsif arg1.kind_of? Register8 and arg2.kind_of? Array then
|
elsif arg1.kind_of? Register8 and arg2.kind_of? Array then
|
if arg2.length>1 or arg2.length<1 or not arg2[0].kind_of? Register8 then
|
if arg2.length>1 or arg2.length<1 or not arg2[0].kind_of? Register8 then
|
raise "memory reference is not correct. Only a register is allowed";
|
raise "memory reference is not correct. Only a register is allowed";
|
end
|
end
|
mov_mreg_reg arg1,arg2[0]
|
mov_reg_mreg arg1,arg2[0]
|
elsif arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
elsif arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
mov_reg_reg arg1, arg2
|
mov_reg_reg arg1, arg2
|
else
|
else
|
raise "No suitable mov opcode found";
|
raise "No suitable mov opcode found";
|
end
|
end
|
end
|
end
|
def and_(arg1,arg2)
|
def and_(arg1,arg2)
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
and_reg_reg arg1,arg2
|
and_reg_reg arg1,arg2
|
else
|
else
|
raise "No suitable and opcode found";
|
raise "No suitable and opcode found";
|
end
|
end
|
end
|
end
|
def or_(arg1,arg2)
|
def or_(arg1,arg2)
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
or_reg_reg arg1,arg2
|
or_reg_reg arg1,arg2
|
else
|
else
|
raise "No suitable or opcode found";
|
raise "No suitable or opcode found";
|
end
|
end
|
end
|
end
|
def xor_(arg1,arg2)
|
def xor_(arg1,arg2)
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
xor_reg_reg arg1,arg2
|
xor_reg_reg arg1,arg2
|
else
|
else
|
raise "No suitable xor opcode found";
|
raise "No suitable xor opcode found";
|
end
|
end
|
end
|
end
|
def not_(arg1,arg2)
|
def not_(arg1,arg2)
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
not_reg_reg arg1,arg2
|
not_reg_reg arg1,arg2
|
else
|
else
|
raise "No suitable not opcode found";
|
raise "No suitable not opcode found";
|
end
|
end
|
end
|
end
|
def rsh(arg1,arg2)
|
def rsh(arg1,arg2)
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
rsh_reg_reg arg1,arg2
|
rsh_reg_reg arg1,arg2
|
else
|
else
|
raise "No suitable rsh opcode found";
|
raise "No suitable rsh opcode found";
|
end
|
end
|
end
|
end
|
def lsh(arg1,arg2)
|
def lsh(arg1,arg2)
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
lsh_reg_reg arg1,arg2
|
lsh_reg_reg arg1,arg2
|
else
|
else
|
raise "No suitable lsh opcode found";
|
raise "No suitable lsh opcode found";
|
end
|
end
|
end
|
end
|
def rro(arg1,arg2)
|
def rro(arg1,arg2)
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
rro_reg_reg arg1,arg2
|
rro_reg_reg arg1,arg2
|
else
|
else
|
raise "No suitable rro opcode found";
|
raise "No suitable rro opcode found";
|
end
|
end
|
end
|
end
|
def lro(arg1,arg2)
|
def lro(arg1,arg2)
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
lro_reg_reg arg1,arg2
|
lro_reg_reg arg1,arg2
|
else
|
else
|
raise "No suitable lro opcode found";
|
raise "No suitable lro opcode found";
|
end
|
end
|
end
|
end
|
|
|
def cmpgt(arg1,arg2)
|
def cmpgt(arg1,arg2)
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
cmpgt_reg_reg arg1,arg2
|
cmpgt_reg_reg arg1,arg2
|
else
|
else
|
raise "No suitable cmpgt opcode found";
|
raise "No suitable cmpgt opcode found";
|
end
|
end
|
end
|
end
|
def cmpgte(arg1,arg2)
|
def cmpgte(arg1,arg2)
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
cmpgte_reg_reg arg1,arg2
|
cmpgte_reg_reg arg1,arg2
|
else
|
else
|
raise "No suitable cmpgte opcode found";
|
raise "No suitable cmpgte opcode found";
|
end
|
end
|
end
|
end
|
def cmplt(arg1,arg2)
|
def cmplt(arg1,arg2)
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
cmplt_reg_reg arg1,arg2
|
cmplt_reg_reg arg1,arg2
|
else
|
else
|
raise "No suitable cmplt opcode found";
|
raise "No suitable cmplt opcode found";
|
end
|
end
|
end
|
end
|
def cmplte(arg1,arg2)
|
def cmplte(arg1,arg2)
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
cmplte_reg_reg arg1,arg2
|
cmplte_reg_reg arg1,arg2
|
else
|
else
|
raise "No suitable cmplte opcode found";
|
raise "No suitable cmplte opcode found";
|
end
|
end
|
end
|
end
|
def cmpeq(arg1,arg2)
|
def cmpeq(arg1,arg2)
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
cmpeq_reg_reg arg1,arg2
|
cmpeq_reg_reg arg1,arg2
|
elsif arg1.kind_of? Register8 and arg2.kind_of? Integer and arg2==0 then
|
elsif arg1.kind_of? Register8 and arg2.kind_of? Integer and arg2==0 then
|
cmpeq_reg_0 arg1
|
cmpeq_reg_0 arg1
|
else
|
else
|
raise "No suitable cmpeq opcode found";
|
raise "No suitable cmpeq opcode found";
|
end
|
end
|
end
|
end
|
def cmpneq(arg1,arg2)
|
def cmpneq(arg1,arg2)
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
if arg1.kind_of? Register8 and arg2.kind_of? Register8 then
|
cmpneq_reg_reg arg1,arg2
|
cmpneq_reg_reg arg1,arg2
|
elsif arg1.kind_of? Register8 and arg2.kind_of? Integer and arg2==0 then
|
elsif arg1.kind_of? Register8 and arg2.kind_of? Integer and arg2==0 then
|
cmpneq_reg_0 arg1
|
cmpneq_reg_0 arg1
|
else
|
else
|
raise "No suitable cmpneq opcode found";
|
raise "No suitable cmpneq opcode found";
|
end
|
end
|
end
|
end
|
|
|
def Label
|
def Label
|
attr_accessor :name, :pos
|
attr_accessor :name, :pos
|
def initialize(name, pos)
|
def initialize(name, pos)
|
@name=name;
|
@name=name;
|
@pos=pos;
|
@pos=pos;
|
end
|
end
|
end
|
end
|
$labellist={}
|
$labellist={}
|
def label(name)
|
def new_label(name)
|
$labellist[name.to_s]=$position;
|
$labellist[name.to_s]=$position;
|
end
|
end
|
def lbl(name)
|
def lbl(name)
|
$labellist[name.to_s]=$position;
|
$labellist[name.to_s];
|
end
|
end
|
|
|
|
|
def if_tr_set
|
def if_tr_set
|
$iftr = 1
|
$iftr = 1
|
yield
|
yield
|
$iftr = 0
|
$iftr = 0
|
end
|
end
|
|
|
|
|
r0=Register8.new(0)
|
r0=Register8.new(0)
|
r1=Register8.new(1)
|
r1=Register8.new(1)
|
r2=Register8.new(2)
|
r2=Register8.new(2)
|
r3=Register8.new(3)
|
r3=Register8.new(3)
|
r4=Register8.new(4)
|
r4=Register8.new(4)
|
r5=Register8.new(5)
|
r5=Register8.new(5)
|
sp=Register8.new(6)
|
sp=Register8.new(6)
|
ip=Register8.new(7)
|
ip=Register8.new(7)
|
|
|
|
|
#test code follows. Only do it here for convenience.. real usage should prefix assembly files with `require "asm.rb"`
|
#test code follows. Only do it here for convenience.. real usage should prefix assembly files with `require "asm.rb"`
|
|
|
|
|
#port0(0) is LED port0(1) is a button
|
#port0(0) is LED port0(1) is a button
|
|
|
mov r4, 1
|
mov r4, 1
|
mov r5, 0x01 #the port bitmask
|
mov r5, 0xFD
|
|
#mov r5, 0x01 #the port bitmask
|
mov [r4],r5
|
mov [r4],r5
|
mov r3, 0
|
mov r3, 0
|
|
mov [r3], 0
|
mov r2, 0x02
|
mov r2, 0x02
|
#poll for button
|
#poll for button
|
label :loop
|
new_label :loop
|
mov r0, [r3]
|
mov r0, [r3]
|
and_ r0, r2 #isolate just the button at pin 2
|
and_ r0, r2 #isolate just the button at pin 2
|
cmpneq r0, 0
|
cmpneq r0, 0
|
if_tr_set{
|
if_tr_set{
|
mov [r3], 0x01
|
mov [r3], 0x01
|
}
|
}
|
cmpeq r0,0
|
cmpeq r0,0
|
if_tr_set{
|
if_tr_set{
|
mov [r3], 0x00
|
mov [r3], 0x00
|
}
|
}
|
mov ip, lbl(:loop)
|
mov ip, lbl(:loop)
|
|
|
printf("\n");
|
printf("\n");
|
while $position<64
|
while $position<64
|
printf("x\"0000\", ")
|
printf("x\"0000\", ")
|
$position+=2;
|
$position+=2;
|
end
|
end
|
puts "\nsize:" + $position.to_s
|
puts "\nsize:" + $position.to_s
|
|
|