URL
https://opencores.org/ocsvn/tinycpu/tinycpu/trunk
Subversion Repositories tinycpu
[/] [tinycpu/] [trunk/] [assembler/] [asm.rb] - Rev 41
Compare with Previous | Blame | View Log
PREFIX = "x\"";SUFFIX = "\"";SEPERATOR = ", ";class OpcodeByte1attr_accessor :op, :register, :cond;def to_hexs = (op << 4 | register.number << 1 | cond).to_s(16);if s.length == 1"0"+s;elsif s.length == 0"00";elsesendendendclass OpcodeByte2attr_accessor :cond, :reg2, :useextra, :reg3;def to_hexs=(cond << 7 | reg2.number << 4 | useextra << 3 | reg3.number).to_s(16);if s.length == 1"0"+s;elsif s.length==0"00";elses;endendendclass Register8attr_accessor :numberdef initialize(num)@number=numendendclass OpcodeOptionattr_accessor :numberdef initialize(num)@number=num;endend$iftr = 0; #0 for no condition, 1 for if TR, 2 for if not TR$useextra = 0;$position = 0;def set_cond(o1, o2)if $iftr==0 theno1.cond=0;o2.cond=0;elsif $iftr==1 theno1.cond=1;o2.cond=0;elseo1.cond=0;o2.cond=1;endenddef output_op(value)printf PREFIX + value + SUFFIX;printf SEPERATOR;$position+=2;enddef mov_r8_imm8(reg,imm)o = OpcodeByte1.new();o.op = 0;o.register=reg;if $iftr<2 theno.cond=$iftr;elseraise "if_tr_notset is not allowed with this opcode";endoutput_op(o.to_hex.rjust(2,"0") + imm.to_s(16).rjust(2,"0"))enddef mov_rm8_imm8(reg,imm)o=OpcodeByte1.new();o.op=1;o.register=reg;if $iftr<2 theno.cond=$iftr;elseraise "if_tr_notset is not allowed with this opcode";endoutput_op(o.to_hex.rjust(2,"0") + imm.to_s(16).rjust(2,"0"));enddef do_group_reg_reg(opcode,group,reg1,reg2)o1 = OpcodeByte1.new()o1.op=opcode;o1.register=reg1;o2 = OpcodeByte2.new()o2.useextra=$useextra;o2.reg2=reg2;o2.reg3=OpcodeOption.new(group); #opcode groupset_cond(o1,o2)output_op(o1.to_hex.rjust(2,"0") + o2.to_hex.rjust(2,"0"))enddef do_subgroup_reg(opcode,group,subgroup,reg1)o1 = OpcodeByte1.new()o1.op=opcode;o1.register=reg1;o2 = OpcodeByte2.new()o2.useextra=$useextra;o2.reg2=OpcodeOption.new(subgroup);o2.reg3=OpcodeOption.new(group); #opcode groupset_cond(o1,o2)output_op(o1.to_hex.rjust(2,"0") + o2.to_hex.rjust(2,"0"))enddef and_reg_reg(reg1, reg2)do_group_reg_reg(4,0,reg1,reg2)end;def or_reg_reg(reg1, reg2)do_group_reg_reg(4,1,reg1,reg2)end;def xor_reg_reg(reg1, reg2)do_group_reg_reg(4,2,reg1,reg2)end;def not_reg_reg(reg1, reg2)do_group_reg_reg(4,3,reg1,reg2)end;def lsh_reg_reg(reg1, reg2)do_group_reg_reg(4,4,reg1,reg2)end;def rsh_reg_reg(reg1, reg2)do_group_reg_reg(4,5,reg1,reg2)end;def lro_reg_reg(reg1, reg2)do_group_reg_reg(4,6,reg1,reg2)end;def rro_reg_reg(reg1, reg2)do_group_reg_reg(4,7,reg1,reg2)end;#comparisonsdef cmpgt_reg_reg(reg1, reg2)do_group_reg_reg(3,0,reg1,reg2)end;def cmpgte_reg_reg(reg1, reg2)do_group_reg_reg(3,1,reg1,reg2)end;def cmplt_reg_reg(reg1, reg2)do_group_reg_reg(3,2,reg1,reg2)end;def cmplte_reg_reg(reg1, reg2)do_group_reg_reg(3,3,reg1,reg2)end;def cmpeq_reg_reg(reg1, reg2)do_group_reg_reg(3,4,reg1,reg2)end;def cmpneq_reg_reg(reg1, reg2)do_group_reg_reg(3,5,reg1,reg2)end;def cmpeq_reg_0(reg1)do_group_reg_reg(3,6,reg1,Register8.new(0)) #last arg isn't usedend;def cmpneq_reg_0(reg1)do_group_reg_reg(3,7,reg1,Register8.new(0))end;def mov_reg_mreg(reg1, reg2)do_group_reg_reg(5,2,reg1,reg2)enddef mov_mreg_reg(reg1, reg2)do_group_reg_reg(5,3,reg1,reg2)enddef mov_reg_reg(reg1, reg2)do_group_reg_reg(5,1,reg1,reg2)enddef mov(arg1,arg2)if arg1.kind_of? Register8 and arg2.kind_of? Integer and arg2<0x100 thenmov_r8_imm8 arg1,arg2elsif arg1.kind_of? Array and arg2.kind_of? Integer and arg2<0x100 thenif arg1.length>1 or arg1.length<1 or not arg1[0].kind_of? Register8 thenraise "memory reference is not correct. Only a register is allowed";endreg=arg1[0];mov_rm8_imm8 reg, arg2elsif arg1.kind_of? Array and arg2.kind_of? Register8 thenif arg1.length>1 or arg1.length<1 or not arg1[0].kind_of? Register8 thenraise "memory reference is not correct. Only a register is allowed";endmov_mreg_reg arg1[0], arg2elsif arg1.kind_of? Register8 and arg2.kind_of? Array thenif arg2.length>1 or arg2.length<1 or not arg2[0].kind_of? Register8 thenraise "memory reference is not correct. Only a register is allowed";endmov_reg_mreg arg1,arg2[0]elsif arg1.kind_of? Register8 and arg2.kind_of? Register8 thenmov_reg_reg arg1, arg2elseraise "No suitable mov opcode found";endenddef and_(arg1,arg2)if arg1.kind_of? Register8 and arg2.kind_of? Register8 thenand_reg_reg arg1,arg2elseraise "No suitable and opcode found";endenddef or_(arg1,arg2)if arg1.kind_of? Register8 and arg2.kind_of? Register8 thenor_reg_reg arg1,arg2elseraise "No suitable or opcode found";endenddef xor_(arg1,arg2)if arg1.kind_of? Register8 and arg2.kind_of? Register8 thenxor_reg_reg arg1,arg2elseraise "No suitable xor opcode found";endenddef not_(arg1,arg2)if arg1.kind_of? Register8 and arg2.kind_of? Register8 thennot_reg_reg arg1,arg2elseraise "No suitable not opcode found";endenddef rsh(arg1,arg2)if arg1.kind_of? Register8 and arg2.kind_of? Register8 thenrsh_reg_reg arg1,arg2elseraise "No suitable rsh opcode found";endenddef lsh(arg1,arg2)if arg1.kind_of? Register8 and arg2.kind_of? Register8 thenlsh_reg_reg arg1,arg2elseraise "No suitable lsh opcode found";endenddef rro(arg1,arg2)if arg1.kind_of? Register8 and arg2.kind_of? Register8 thenrro_reg_reg arg1,arg2elseraise "No suitable rro opcode found";endenddef lro(arg1,arg2)if arg1.kind_of? Register8 and arg2.kind_of? Register8 thenlro_reg_reg arg1,arg2elseraise "No suitable lro opcode found";endenddef cmpgt(arg1,arg2)if arg1.kind_of? Register8 and arg2.kind_of? Register8 thencmpgt_reg_reg arg1,arg2elseraise "No suitable cmpgt opcode found";endenddef cmpgte(arg1,arg2)if arg1.kind_of? Register8 and arg2.kind_of? Register8 thencmpgte_reg_reg arg1,arg2elseraise "No suitable cmpgte opcode found";endenddef cmplt(arg1,arg2)if arg1.kind_of? Register8 and arg2.kind_of? Register8 thencmplt_reg_reg arg1,arg2elseraise "No suitable cmplt opcode found";endenddef cmplte(arg1,arg2)if arg1.kind_of? Register8 and arg2.kind_of? Register8 thencmplte_reg_reg arg1,arg2elseraise "No suitable cmplte opcode found";endenddef cmpeq(arg1,arg2)if arg1.kind_of? Register8 and arg2.kind_of? Register8 thencmpeq_reg_reg arg1,arg2elsif arg1.kind_of? Register8 and arg2.kind_of? Integer and arg2==0 thencmpeq_reg_0 arg1elseraise "No suitable cmpeq opcode found";endenddef cmpneq(arg1,arg2)if arg1.kind_of? Register8 and arg2.kind_of? Register8 thencmpneq_reg_reg arg1,arg2elsif arg1.kind_of? Register8 and arg2.kind_of? Integer and arg2==0 thencmpneq_reg_0 arg1elseraise "No suitable cmpneq opcode found";endenddef Labelattr_accessor :name, :posdef initialize(name, pos)@name=name;@pos=pos;endend$labellist={}def new_label(name)$labellist[name.to_s]=$position;enddef lbl(name)$labellist[name.to_s];enddef if_tr_set$iftr = 1yield$iftr = 0endr0=Register8.new(0)r1=Register8.new(1)r2=Register8.new(2)r3=Register8.new(3)r4=Register8.new(4)r5=Register8.new(5)sp=Register8.new(6)ip=Register8.new(7)#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 buttonmov r4, 1mov r5, 0xFD#mov r5, 0x01 #the port bitmaskmov [r4],r5mov r3, 0mov [r3], 0mov r2, 0x02#poll for buttonnew_label :loopmov r0, [r3]and_ r0, r2 #isolate just the button at pin 2cmpneq r0, 0if_tr_set{mov [r3], 0x01}cmpeq r0,0if_tr_set{mov [r3], 0x00}mov ip, lbl(:loop)printf("\n");while $position<64printf("x\"0000\", ")$position+=2;endputs "\nsize:" + $position.to_s
