123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648 |
- use32
- org 0
- macro print_digit v* {
- local a
- a = (v and $F) + '0'
- if a > '9'
- a = a + ('A' - '9' - 1)
- end if
- db a
- }
- macro print_word v* {
- local a
- a = 7
- while a >= 0
- print_digit (v shr (4*a))
- a = a-1
- end while
- }
- macro print_halfword v* {
- local a
- a = 3
- while a >= 0
- print_digit (v shr (4*a))
- a = a-1
- end while
- }
- macro print_byte v* {
- local a
- a = 1
- while a >= 0
- print_digit (v shr (4*a))
- a = a-1
- end while
- }
- _zero = 0
- _at = 1
- _v0 = 2
- _v1 = 3
- _a0 = 4
- _a1 = 5
- _a2 = 6
- _a3 = 7
- _t0 = 8
- _t1 = 9
- _t2 = 10
- _t3 = 11
- _t4 = 12
- _t5 = 13
- _t6 = 14
- _t7 = 15
- _s0 = 16
- _s1 = 17
- _s2 = 18
- _s3 = 19
- _s4 = 20
- _s5 = 21
- _s6 = 22
- _s7 = 23
- _t8 = 24
- _t9 = 25
- _k0 = 26
- _k1 = 27
- _gp = 28
- _sp = 29
- _fp = 30
- _ra = 31
- macro _register_name n {
- if n = _zero
- db '$zero'
- else if n = _at
- db '$at'
- else if n >= _v0 & n <= _v1
- db '$v', (n-_v0+'0')
- else if n >= _a0 & n <= _a3
- db '$a', (n-_a0+'0')
- else if n >= _t0 & n <= _t7
- db '$t', (n-_t0+'0')
- else if n >= _s0 & n <= _s7
- db '$s', (n-_s0+'0')
- else if n >= _t8 & n <= _t9
- db '$t', (n-_t8+'8')
- else if n >= _k0 & n <= _k1
- db '$k', (n-_k0+'0')
- else if n = _gp
- db '$gp'
- else if n = _sp
- db '$sp'
- else if n = _fp
- db '$fp'
- else if n = _ra
- db '$ra'
- end if
- }
- macro __clear {
- _a=0
- _b=0
- _c=0
- _d=0
- _e=0
- _f=0 }
- macro __opcode _ { _a = (_ and 0111111b) shl (32-6) }
- macro __rs _ { _b = (_ and 011111b) shl (32-6-5) }
- macro __rt _ { _c = (_ and 011111b) shl (32-6-5-5) }
- macro __rd _ { _d = (_ and 011111b) shl (32-6-5-5-5) }
- macro __shamt _ { _e = (_ and 011111b) shl (32-6-5-5-5-5) }
- macro __func _ { _f = (_ and 0111111b) }
- macro __imm _ { _d = (_ and 0xFFFF) }
- macro __addr _ { _b = (_ and 0x3FFFFFF) }
- ; 1111 1111 1111 1111 - 1111 1111 1111 1111
- ; F F F F - F F F F
- ; 1111 1111 1111 1111 - 1111 1111 1111 1111
- ; 32 28 24 20 16 12 8 4
- ; 1111 1111 1111 1111 - 1111 1111 1111 1111
- ; ^ 3 F^ opcode
- ; 1111 1111 1111 1111 - 1111 1111 1111 1111
- ; ^ 1F ^ rs
- ; 1111 1111 1111 1111 - 1111 1111 1111 1111
- ; ^ 3 F F F F F F^ address
- ; 1111 1111 1111 1111 - 1111 1111 1111 1111
- ; ^ 1F ^ rt
- ; 1111 1111 1111 1111 - 1111 1111 1111 1111
- ; ^ 1F ^ rd
- ; 1111 1111 1111 1111 - 1111 1111 1111 1111
- ; ^ F F F F^ immediate
- ; 1111 1111 1111 1111 - 1111 1111 1111 1111
- ; ^ 1F ^ shamt
- ; 1111 1111 1111 1111 - 1111 1111 1111 1111
- ; ^ 3 F^ func
- ; Print registers' names
- macro print_instr_reg _name*, [_reg] {
- common
- db ' ',_name
- forward
- db ' '
- _register_name _reg
- db ','
- common
- store byte 10 at $-1
- }
- ; Print registers then an immediate
- macro print_instr_rimm _name*, _imm*, [_reg] {
- common
- db ' ',_name
- forward
- db ' '
- _register_name _reg
- db ','
- common
- if _imm <= $FF
- db ' 0x'
- print_byte _imm
- else if _imm <= $FFFF
- db ' 0x'
- print_halfword _imm
- else
- ;print_word _imm
- ;db ' # ',`_imm
- db ' ',`_imm
- end if
- db 10
- }
- ; Print an address
- macro print_instr_addr _name*, _addr* {
- db ' ',_name,' '
- db `_addr
- db 10
- }
- ; Print $X, imm($Y)
- macro print_instr_rrel _name*, _rt*, _imm*, _rs* {
- db ' ',_name,' '
- _register_name _rt
- db ', 0x'
- if _imm <= $FF
- print_byte _imm
- else if _imm <= $FFFF
- print_halfword _imm
- else
- ;print_word _imm
- db ' # ',`_imm
- end if
- db '('
- _register_name _rs
- db ')',10
- }
- macro R _rs*, _rt*, _rd*, _shamt*, _func* {
- __clear
- __opcode 0
- __rs _rs
- __rt _rt
- __rd _rd
- __shamt _shamt
- __func _func
- virtual defaultSpace
- print_word (_a+_b+_c+_d+_e+_f)
- end virtual
- }
- ;_add _t0, _t1, _t2 -> R _t1, _t2, _t0, 0, 32 -> 0x012A4020
- ; Unsigned left shift / logical left shift
- macro _sll _rd*, _rt*, _shamt* {
- print_instr_rimm 'sll',_shamt, _rd, _rt
- R 0, _rt, _rd, _shamt, 0 }
- ; Unsigned right shift / logical right shift
- macro _srl _rd*, _rt*, _shamt* {
- print_instr_rimm 'srl',_shamt, _rd, _rt
- R 0, _rt, _rd, _shamt, 2 }
- ; Signed right shift / arithmetic right shift
- macro _sra _rd*, _rt*, _shamt* {
- print_instr_rimm 'sra',_shamt, _rd, _rt
- R 0, _rt, _rd, _shamt, 3 }
- ; Unsigned left shift with register
- macro _sllv _rd*, _rt*, _rs* {
- print_instr_reg 'sllv', _rd, _rt, _rs
- R _rs, _rt, _rd, 0, 4 }
- ; Unsigned right shift with register
- macro _srlv _rd*, _rt*, _rs* {
- print_instr_reg 'srlv', _rd, _rt, _rs
- R _rs, _rt, _rd, 0, 6 }
- ; Signed right shift with register
- macro _srav _rd*, _rt*, _rs* {
- print_instr_reg 'srav', _rd, _rt, _rs
- R _rs, _rt, _rd, 0, 7 }
- ; Jump to register
- macro _jr _rs* {
- print_instr_reg 'jr', _rs
- R _rs, 0, 0, 0, 8 }
- ; Jump and link to registers
- macro _jalr _rd=_ra, _rs* {
- if _rd=_ra
- print_instr_reg 'jalr', _rs
- else
- print_instr_reg 'jalr', _rd, _rs
- end if
- R _rs, 0, _rd, 0, 9 }
- ; Syscall
- macro _syscall {
- _asm ' syscall'
- R 0, 0, 0, 0, 12 }
- ; Move from hi
- macro _mfhi _rd* {
- print_instr_reg 'mfhi', _rd
- R 0, 0, _rd, 0, 16 }
- ; Move to hi
- macro _mthi _rs* {
- print_instr_reg 'mthi', _rs
- R _rs, 0, 0, 0, 17 }
- ; Move from lo
- macro _mflo _rd* {
- print_instr_reg 'mflo', _rd
- R 0, 0, _rd, 0, 18 }
- ; Move to lo
- macro _mtlo _rs* {
- print_instr_reg 'mtlo', _rs
- R _rs, 0, 0, 0, 19 }
- ; Signed multiplication
- macro _mult _rs*, _rt* {
- print_instr_reg 'mult', _rs, _rt
- R _rs, _rt, 0, 0, 24 }
- ; Unsigned multiplication
- macro _multu _rs*, _rt* {
- print_instr_reg 'multu', _rs, _rt
- R _rs, _rt, 0, 0, 25 }
- ; Signed division
- macro _div _rs*, _rt* {
- print_instr_reg 'div', _rs, _rt
- R _rs, _rt, 0, 0, 26 }
- ; Unsigned division
- macro _divu _rs*, _rt* {
- print_instr_reg 'divu', _rs, _rt
- R _rs, _rt, 0, 0, 27 }
- ; Add signed / add and raise exception on signed overflow
- macro _add _rd*, _rs*, _rt* {
- print_instr_reg 'add', _rd, _rs, _rt
- R _rs, _rt, _rd, 0, 32 }
- ; Add unsigned
- macro _addu _rd*, _rs*, _rt* {
- print_instr_reg 'addu', _rd, _rs, _rt
- R _rs, _rt, _rd, 0, 33 }
- ; Subtract signed / subtract and raise exception on signed overflow
- macro _sub _rd*, _rs*, _rt* {
- print_instr_reg 'sub', _rd, _rs, _rt
- R _rs, _rt, _rd, 0, 34 }
- ; Subtract unsigned
- macro _subu _rd*, _rs*, _rt* {
- print_instr_reg 'subu', _rd, _rs, _rt
- R _rs, _rt, _rd, 0, 35 }
- macro _and _rd*, _rs*, _rt* {
- print_instr_reg 'and', _rd, _rs, _rt
- R _rs, _rt, _rd, 0, 36 }
- macro _or _rd*, _rs*, _rt* {
- print_instr_reg 'or', _rd, _rs, _rt
- R _rs, _rt, _rd, 0, 37 }
- macro _xor _rd*, _rs*, _rt* {
- print_instr_reg 'xor', _rd, _rs, _rt
- R _rs, _rt, _rd, 0, 38 }
- macro _nor _rd*, _rs*, _rt* {
- print_instr_reg 'nor', _rd, _rs, _rt
- R _rs, _rt, _rd, 0, 39 }
- ; Signed compare rs < rt
- macro _slt _rd*, _rs*, _rt* {
- print_instr_reg 'slt', _rd, _rs, _rt
- R _rs, _rt, _rd, 0, 42 }
- ; Unsigned compare rs < rt
- macro _sltu _rd*, _rs*, _rt* {
- print_instr_reg 'sltu', _rd, _rs, _rt
- R _rs, _rt, _rd, 0, 43 }
- macro _move _rt*, _rs* {
- ;db ' # move '
- ;_register_name _rt
- ;db ', '
- ;_register_name _rs
- ;db 10
- _addu _rt, _zero, _rs }
- macro _nop {
- virtual defaultSpace
- dd 0
- end virtual
- db 'nop',10
- }
- macro J _op*, _addr* {
- __clear
- __opcode _op
- __addr _addr
- virtual defaultSpace
- print_word (_a+_b)
- end virtual
- }
- macro _j _addr* {
- print_instr_addr 'j', _addr
- J 2, (_addr shr 2) }
- macro _jal _addr* {
- print_instr_addr 'jal', _addr
- J 3, (_addr shr 2) }
- macro I _op*, _rs*, _rt*, _imm* {
- __clear
- __opcode _op
- __rs _rs
- __rt _rt
- __imm _imm
- virtual defaultSpace
- print_word (_a+_b+_c+_d)
- end virtual
- }
- macro _beq _rs*, _rt*, _imm* {
- print_instr_rimm 'beq', _imm, _rs, _rt
- I 4, _rs, _rt, (_imm shr 2) }
- macro _bne _rs*, _rt*, _imm* {
- print_instr_rimm 'bne', _imm, _rs, _rt
- I 5, _rs, _rt, (_imm shr 2) }
- ;Branch if less or equal/greater than zero
- macro _blez _rs*, _imm* {
- print_instr_rimm 'blez', _imm, _rs
- I 6, _rs, 0, (_imm shr 2) }
- macro _bgtz _rs*, _imm* {
- print_instr_rimm 'bgtz', _imm, _rs
- I 7, _rs, 0, (_imm shr 2) }
- ; Add immediate
- macro _addi _rt*, _rs*, _imm* {
- print_instr_rimm 'addi', _imm, _rt, _rs
- I 8, _rs, _rt, _imm }
- macro _addiu _rt*, _rs*, _imm* {
- print_instr_rimm 'addiu', _imm, _rt, _rs
- I 9, _rs, _rt, _imm }
- macro _subi _rt*, _rs*, _imm* {
- _li _at, _imm
- _sub _rt, _rs, _at }
- macro _subiu _rt*, _rs*, _imm* {
- _li _at, _imm
- _subu _rt, _rs, _at }
- ; Comparision with immediate
- macro _slti _rt*, _rs*, _imm* {
- print_instr_rimm 'slti', _imm, _rt, _rs
- I 10, _rs, _rt, _imm }
- macro _sltiu _rt*, _rs*, _imm* {
- print_instr_rimm 'sltiu', _imm, _rt, _rs
- I 11, _rs, _rt, _imm }
- ; Logic with constants
- macro _andi _rt*, _rs*, _imm* {
- print_instr_rimm 'andi', _imm, _rt, _rs
- I 12, _rs, _rt, _imm }
- macro _ori _rt*, _rs*, _imm* {
- print_instr_rimm 'ori', _imm, _rt, _rs
- I 13, _rs, _rt, _imm }
- macro _xori _rt*, _rs*, _imm* {
- print_instr_rimm 'xori', _imm, _rt, _rs
- I 14, _rs, _rt, _imm }
- ; Load from main memory
- macro _lui _rt*, _imm* {
- print_instr_rimm 'lui', _imm, _rt
- I 15, 0, _rt, _imm }
- macro _lb _rt*, _imm=0, _rs* {
- print_instr_rrel 'lb', _rt, _imm, _rs
- I 32, _rs, _rt, _imm }
- macro _lh _rt*, _imm*, _rs* {
- print_instr_rrel 'lh', _rt, _imm, _rs
- I 33, _rs, _rt, _imm }
- macro _lw _rt*, _imm*, _rs* {
- print_instr_rrel 'lw', _rt, _imm, _rs
- I 34, _rs, _rt, _imm }
- macro _lbu _rt*, _imm*, _rs* {
- print_instr_rrel 'lbu', _rt, _imm, _rs
- I 36, _rs, _rt, _imm }
- macro _lhu _rt*, _imm*, _rs* {
- print_instr_rrel 'lhu', _rt, _imm, _rs
- I 37, _rs, _rt, _imm }
- macro _li _rt*, _imm32* {
- ; db ' # li '
- ; _register_name _rt
- ; db ', 0x'
- ;if _imm32 <= $FF
- ; print_byte _imm32
- ;else if _imm32 <= $FFFF
- ; print_halfword _imm32
- ;else
- ; print_word _imm32
- ;end if
- ; db ' # ',`_imm32
- ; db 10
- if _imm32 > 0xFFFF
- _lui _rt, (_imm32 shr 16)
- if (_imm32 and 0xFFFF) > 0
- _ori _rt, _rt, (_imm32 and 0xFFFF)
- end if
- else
- _addiu _rt, _zero, _imm32
- end if
- }
- macro _la _rt*, _imm32* {
- ; db ' # la '
- ; _register_name _rt
- ; db ', 0x'
- ; print_word _imm32
- ; db ' # ',`_imm32
- ; db 10
- if _imm32 > 0xFFFF
- _lui _rt, (_imm32 shr 16)
- if (_imm32 and 0xFFFF) > 0
- _ori _rt, _rt, (_imm32 and 0xFFFF)
- end if
- else
- _addiu _rt, _zero, _imm32
- end if
- }
- ; Store on main memory
- macro _sb _rt*, _imm*, _rs* {
- print_instr_rrel 'sb', _rt, _imm, _rs
- I 40, _rs, _rt, _imm }
- macro _sh _rt*, _imm*, _rs* {
- print_instr_rrel 'sh', _rt, _imm, _rs
- I 41, _rs, _rt, _imm }
- macro _sw _rt*, _imm*, _rs* {
- print_instr_rrel 'sw', _rt, _imm, _rs
- I 43, _rs, _rt, _imm }
- ; SPIM macros
- defaultSpace equ _Text
- macro _asm text {
- db text,10
- }
- macro _noat {
- _asm '.set noat'
- }
- macro _at {
- _asm '.set at'
- }
- macro _comment text {
- db '# ',text,10
- }
- macro _comment_append text {
- store byte ' ' at $-1
- db '# ',text,10
- }
- virtual at 0x00400024
- _Text::
- end virtual
- macro _ttext {
- local addr
- virtual _Text
- addr:
- end virtual
- _addr = addr
- db '.text 0x'
- print_word _addr
- db 10
- purge _addr
- defaultSpace equ _Text
- }
- macro _dtext {
- local addr
- virtual _Text
- addr:
- end virtual
- _addr = addr
- db '.data 0x'
- print_word _addr
- db 10
- purge _addr
- defaultSpace equ _Text
- }
- macro _globl _lbl {
- db '.globl ',`_lbl,10
- }
- virtual at 0x10010000
- _Data::
- end virtual
- macro _ddata {
- local addr
- virtual _Data
- addr:
- end virtual
- _addr = addr
- db '.data 0x'
- print_word _addr
- db 10
- purge _addr
- defaultSpace equ _Data
- }
- macro _word [v] {
- common
- virtual defaultSpace
- forward
- dd v
- common
- end virtual
- forward
- db ' .word 0x'
- print_word v
- db 10
- }
- macro _dw [v] {
- _word v
- }
- macro _half [v] {
- common
- virtual defaultSpace
- forward
- dw v
- common
- end virtual
- forward
- db ' .half 0x'
- print_halfword v
- db 10
- }
- macro _dh [v] {
- _half v
- }
- macro _byte [v] {
- common
- virtual defaultSpace
- forward
- db v
- common
- end virtual
- forward
- db ' .byte 0x'
- print_byte v
- db 10
- }
- macro _db [v] {
- _byte v
- }
- macro _asciiz t {
- local last
- virtual defaultSpace
- db t,0
- end virtual
- db ' .asciiz "'
- db t
- load last byte from $-1
- if last = 10
- store byte '\' at $-1
- db 'n'
- end if
- db '"',10
- }
- macro _space len {
- db '.space 0x'
- print_halfword len
- db 10
- virtual defaultSpace
- rb len
- end virtual
- }
- macro _rw len {
- _space (len*4)
- }
- macro _rh len {
- _space (len*2)
- }
- macro _rb len {
- _space len
- }
- macro _label name {
- _asm <`name,':'>
- virtual defaultSpace
- name:
- end virtual
- }
- macro _align expoent {
- _asm <'.align ',`expoent>
- virtual defaultSpace
- align (2 shl (expoent-1))
- end virtual
- }
- ; SPIM syscalls
- spim_service:
- .puti = 1
- .putf = 2
- .putd = 3
- .puts = 4
- .geti = 5
- .getf = 6
- .getd = 7
- .gets = 8
- .sbrk = 9
- .exit = 10
- .putc = 11
- .getc = 12
- .open = 13
- .read = 14
- .write = 15
- .close = 16
- .exit2 = 17
- spim_service.filemode.r = 0
- spim_service.filemode.w = 1
|