mips.asm 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. use32
  2. org 0
  3. macro print_digit v* {
  4. local a
  5. a = (v and $F) + '0'
  6. if a > '9'
  7. a = a + ('A' - '9' - 1)
  8. end if
  9. db a
  10. }
  11. macro print_word v* {
  12. local a
  13. a = 7
  14. while a >= 0
  15. print_digit (v shr (4*a))
  16. a = a-1
  17. end while
  18. }
  19. macro print_halfword v* {
  20. local a
  21. a = 3
  22. while a >= 0
  23. print_digit (v shr (4*a))
  24. a = a-1
  25. end while
  26. }
  27. macro print_byte v* {
  28. local a
  29. a = 1
  30. while a >= 0
  31. print_digit (v shr (4*a))
  32. a = a-1
  33. end while
  34. }
  35. _zero = 0
  36. _at = 1
  37. _v0 = 2
  38. _v1 = 3
  39. _a0 = 4
  40. _a1 = 5
  41. _a2 = 6
  42. _a3 = 7
  43. _t0 = 8
  44. _t1 = 9
  45. _t2 = 10
  46. _t3 = 11
  47. _t4 = 12
  48. _t5 = 13
  49. _t6 = 14
  50. _t7 = 15
  51. _s0 = 16
  52. _s1 = 17
  53. _s2 = 18
  54. _s3 = 19
  55. _s4 = 20
  56. _s5 = 21
  57. _s6 = 22
  58. _s7 = 23
  59. _t8 = 24
  60. _t9 = 25
  61. _k0 = 26
  62. _k1 = 27
  63. _gp = 28
  64. _sp = 29
  65. _fp = 30
  66. _ra = 31
  67. macro _register_name n {
  68. if n = _zero
  69. db '$zero'
  70. else if n = _at
  71. db '$at'
  72. else if n >= _v0 & n <= _v1
  73. db '$v', (n-_v0+'0')
  74. else if n >= _a0 & n <= _a3
  75. db '$a', (n-_a0+'0')
  76. else if n >= _t0 & n <= _t7
  77. db '$t', (n-_t0+'0')
  78. else if n >= _s0 & n <= _s7
  79. db '$s', (n-_s0+'0')
  80. else if n >= _t8 & n <= _t9
  81. db '$t', (n-_t8+'8')
  82. else if n >= _k0 & n <= _k1
  83. db '$k', (n-_k0+'0')
  84. else if n = _gp
  85. db '$gp'
  86. else if n = _sp
  87. db '$sp'
  88. else if n = _fp
  89. db '$fp'
  90. else if n = _ra
  91. db '$ra'
  92. end if
  93. }
  94. macro __clear {
  95. _a=0
  96. _b=0
  97. _c=0
  98. _d=0
  99. _e=0
  100. _f=0 }
  101. macro __opcode _ { _a = (_ and 0111111b) shl (32-6) }
  102. macro __rs _ { _b = (_ and 011111b) shl (32-6-5) }
  103. macro __rt _ { _c = (_ and 011111b) shl (32-6-5-5) }
  104. macro __rd _ { _d = (_ and 011111b) shl (32-6-5-5-5) }
  105. macro __shamt _ { _e = (_ and 011111b) shl (32-6-5-5-5-5) }
  106. macro __func _ { _f = (_ and 0111111b) }
  107. macro __imm _ { _d = (_ and 0xFFFF) }
  108. macro __addr _ { _b = (_ and 0x3FFFFFF) }
  109. ; 1111 1111 1111 1111 - 1111 1111 1111 1111
  110. ; F F F F - F F F F
  111. ; 1111 1111 1111 1111 - 1111 1111 1111 1111
  112. ; 32 28 24 20 16 12 8 4
  113. ; 1111 1111 1111 1111 - 1111 1111 1111 1111
  114. ; ^ 3 F^ opcode
  115. ; 1111 1111 1111 1111 - 1111 1111 1111 1111
  116. ; ^ 1F ^ rs
  117. ; 1111 1111 1111 1111 - 1111 1111 1111 1111
  118. ; ^ 3 F F F F F F^ address
  119. ; 1111 1111 1111 1111 - 1111 1111 1111 1111
  120. ; ^ 1F ^ rt
  121. ; 1111 1111 1111 1111 - 1111 1111 1111 1111
  122. ; ^ 1F ^ rd
  123. ; 1111 1111 1111 1111 - 1111 1111 1111 1111
  124. ; ^ F F F F^ immediate
  125. ; 1111 1111 1111 1111 - 1111 1111 1111 1111
  126. ; ^ 1F ^ shamt
  127. ; 1111 1111 1111 1111 - 1111 1111 1111 1111
  128. ; ^ 3 F^ func
  129. ; Print registers' names
  130. macro print_instr_reg _name*, [_reg] {
  131. common
  132. db ' ',_name
  133. forward
  134. db ' '
  135. _register_name _reg
  136. db ','
  137. common
  138. store byte 10 at $-1
  139. }
  140. ; Print registers then an immediate
  141. macro print_instr_rimm _name*, _imm*, [_reg] {
  142. common
  143. db ' ',_name
  144. forward
  145. db ' '
  146. _register_name _reg
  147. db ','
  148. common
  149. if _imm <= $FF
  150. db ' 0x'
  151. print_byte _imm
  152. else if _imm <= $FFFF
  153. db ' 0x'
  154. print_halfword _imm
  155. else
  156. ;print_word _imm
  157. ;db ' # ',`_imm
  158. db ' ',`_imm
  159. end if
  160. db 10
  161. }
  162. ; Print an address
  163. macro print_instr_addr _name*, _addr* {
  164. db ' ',_name,' '
  165. db `_addr
  166. db 10
  167. }
  168. ; Print $X, imm($Y)
  169. macro print_instr_rrel _name*, _rt*, _imm*, _rs* {
  170. db ' ',_name,' '
  171. _register_name _rt
  172. db ', 0x'
  173. if _imm <= $FF
  174. print_byte _imm
  175. else if _imm <= $FFFF
  176. print_halfword _imm
  177. else
  178. ;print_word _imm
  179. db ' # ',`_imm
  180. end if
  181. db '('
  182. _register_name _rs
  183. db ')',10
  184. }
  185. macro R _rs*, _rt*, _rd*, _shamt*, _func* {
  186. __clear
  187. __opcode 0
  188. __rs _rs
  189. __rt _rt
  190. __rd _rd
  191. __shamt _shamt
  192. __func _func
  193. virtual defaultSpace
  194. print_word (_a+_b+_c+_d+_e+_f)
  195. end virtual
  196. }
  197. ;_add _t0, _t1, _t2 -> R _t1, _t2, _t0, 0, 32 -> 0x012A4020
  198. ; Unsigned left shift / logical left shift
  199. macro _sll _rd*, _rt*, _shamt* {
  200. print_instr_rimm 'sll',_shamt, _rd, _rt
  201. R 0, _rt, _rd, _shamt, 0 }
  202. ; Unsigned right shift / logical right shift
  203. macro _srl _rd*, _rt*, _shamt* {
  204. print_instr_rimm 'srl',_shamt, _rd, _rt
  205. R 0, _rt, _rd, _shamt, 2 }
  206. ; Signed right shift / arithmetic right shift
  207. macro _sra _rd*, _rt*, _shamt* {
  208. print_instr_rimm 'sra',_shamt, _rd, _rt
  209. R 0, _rt, _rd, _shamt, 3 }
  210. ; Unsigned left shift with register
  211. macro _sllv _rd*, _rt*, _rs* {
  212. print_instr_reg 'sllv', _rd, _rt, _rs
  213. R _rs, _rt, _rd, 0, 4 }
  214. ; Unsigned right shift with register
  215. macro _srlv _rd*, _rt*, _rs* {
  216. print_instr_reg 'srlv', _rd, _rt, _rs
  217. R _rs, _rt, _rd, 0, 6 }
  218. ; Signed right shift with register
  219. macro _srav _rd*, _rt*, _rs* {
  220. print_instr_reg 'srav', _rd, _rt, _rs
  221. R _rs, _rt, _rd, 0, 7 }
  222. ; Jump to register
  223. macro _jr _rs* {
  224. print_instr_reg 'jr', _rs
  225. R _rs, 0, 0, 0, 8 }
  226. ; Jump and link to registers
  227. macro _jalr _rd=_ra, _rs* {
  228. if _rd=_ra
  229. print_instr_reg 'jalr', _rs
  230. else
  231. print_instr_reg 'jalr', _rd, _rs
  232. end if
  233. R _rs, 0, _rd, 0, 9 }
  234. ; Syscall
  235. macro _syscall {
  236. _asm ' syscall'
  237. R 0, 0, 0, 0, 12 }
  238. ; Move from hi
  239. macro _mfhi _rd* {
  240. print_instr_reg 'mfhi', _rd
  241. R 0, 0, _rd, 0, 16 }
  242. ; Move to hi
  243. macro _mthi _rs* {
  244. print_instr_reg 'mthi', _rs
  245. R _rs, 0, 0, 0, 17 }
  246. ; Move from lo
  247. macro _mflo _rd* {
  248. print_instr_reg 'mflo', _rd
  249. R 0, 0, _rd, 0, 18 }
  250. ; Move to lo
  251. macro _mtlo _rs* {
  252. print_instr_reg 'mtlo', _rs
  253. R _rs, 0, 0, 0, 19 }
  254. ; Signed multiplication
  255. macro _mult _rs*, _rt* {
  256. print_instr_reg 'mult', _rs, _rt
  257. R _rs, _rt, 0, 0, 24 }
  258. ; Unsigned multiplication
  259. macro _multu _rs*, _rt* {
  260. print_instr_reg 'multu', _rs, _rt
  261. R _rs, _rt, 0, 0, 25 }
  262. ; Signed division
  263. macro _div _rs*, _rt* {
  264. print_instr_reg 'div', _rs, _rt
  265. R _rs, _rt, 0, 0, 26 }
  266. ; Unsigned division
  267. macro _divu _rs*, _rt* {
  268. print_instr_reg 'divu', _rs, _rt
  269. R _rs, _rt, 0, 0, 27 }
  270. ; Add signed / add and raise exception on signed overflow
  271. macro _add _rd*, _rs*, _rt* {
  272. print_instr_reg 'add', _rd, _rs, _rt
  273. R _rs, _rt, _rd, 0, 32 }
  274. ; Add unsigned
  275. macro _addu _rd*, _rs*, _rt* {
  276. print_instr_reg 'addu', _rd, _rs, _rt
  277. R _rs, _rt, _rd, 0, 33 }
  278. ; Subtract signed / subtract and raise exception on signed overflow
  279. macro _sub _rd*, _rs*, _rt* {
  280. print_instr_reg 'sub', _rd, _rs, _rt
  281. R _rs, _rt, _rd, 0, 34 }
  282. ; Subtract unsigned
  283. macro _subu _rd*, _rs*, _rt* {
  284. print_instr_reg 'subu', _rd, _rs, _rt
  285. R _rs, _rt, _rd, 0, 35 }
  286. macro _and _rd*, _rs*, _rt* {
  287. print_instr_reg 'and', _rd, _rs, _rt
  288. R _rs, _rt, _rd, 0, 36 }
  289. macro _or _rd*, _rs*, _rt* {
  290. print_instr_reg 'or', _rd, _rs, _rt
  291. R _rs, _rt, _rd, 0, 37 }
  292. macro _xor _rd*, _rs*, _rt* {
  293. print_instr_reg 'xor', _rd, _rs, _rt
  294. R _rs, _rt, _rd, 0, 38 }
  295. macro _nor _rd*, _rs*, _rt* {
  296. print_instr_reg 'nor', _rd, _rs, _rt
  297. R _rs, _rt, _rd, 0, 39 }
  298. ; Signed compare rs < rt
  299. macro _slt _rd*, _rs*, _rt* {
  300. print_instr_reg 'slt', _rd, _rs, _rt
  301. R _rs, _rt, _rd, 0, 42 }
  302. ; Unsigned compare rs < rt
  303. macro _sltu _rd*, _rs*, _rt* {
  304. print_instr_reg 'sltu', _rd, _rs, _rt
  305. R _rs, _rt, _rd, 0, 43 }
  306. macro _move _rt*, _rs* {
  307. ;db ' # move '
  308. ;_register_name _rt
  309. ;db ', '
  310. ;_register_name _rs
  311. ;db 10
  312. _addu _rt, _zero, _rs }
  313. macro _nop {
  314. virtual defaultSpace
  315. dd 0
  316. end virtual
  317. db 'nop',10
  318. }
  319. macro J _op*, _addr* {
  320. __clear
  321. __opcode _op
  322. __addr _addr
  323. virtual defaultSpace
  324. print_word (_a+_b)
  325. end virtual
  326. }
  327. macro _j _addr* {
  328. print_instr_addr 'j', _addr
  329. J 2, (_addr shr 2) }
  330. macro _jal _addr* {
  331. print_instr_addr 'jal', _addr
  332. J 3, (_addr shr 2) }
  333. macro I _op*, _rs*, _rt*, _imm* {
  334. __clear
  335. __opcode _op
  336. __rs _rs
  337. __rt _rt
  338. __imm _imm
  339. virtual defaultSpace
  340. print_word (_a+_b+_c+_d)
  341. end virtual
  342. }
  343. macro _beq _rs*, _rt*, _imm* {
  344. print_instr_rimm 'beq', _imm, _rs, _rt
  345. I 4, _rs, _rt, (_imm shr 2) }
  346. macro _bne _rs*, _rt*, _imm* {
  347. print_instr_rimm 'bne', _imm, _rs, _rt
  348. I 5, _rs, _rt, (_imm shr 2) }
  349. ;Branch if less or equal/greater than zero
  350. macro _blez _rs*, _imm* {
  351. print_instr_rimm 'blez', _imm, _rs
  352. I 6, _rs, 0, (_imm shr 2) }
  353. macro _bgtz _rs*, _imm* {
  354. print_instr_rimm 'bgtz', _imm, _rs
  355. I 7, _rs, 0, (_imm shr 2) }
  356. ; Add immediate
  357. macro _addi _rt*, _rs*, _imm* {
  358. print_instr_rimm 'addi', _imm, _rt, _rs
  359. I 8, _rs, _rt, _imm }
  360. macro _addiu _rt*, _rs*, _imm* {
  361. print_instr_rimm 'addiu', _imm, _rt, _rs
  362. I 9, _rs, _rt, _imm }
  363. macro _subi _rt*, _rs*, _imm* {
  364. _li _at, _imm
  365. _sub _rt, _rs, _at }
  366. macro _subiu _rt*, _rs*, _imm* {
  367. _li _at, _imm
  368. _subu _rt, _rs, _at }
  369. ; Comparision with immediate
  370. macro _slti _rt*, _rs*, _imm* {
  371. print_instr_rimm 'slti', _imm, _rt, _rs
  372. I 10, _rs, _rt, _imm }
  373. macro _sltiu _rt*, _rs*, _imm* {
  374. print_instr_rimm 'sltiu', _imm, _rt, _rs
  375. I 11, _rs, _rt, _imm }
  376. ; Logic with constants
  377. macro _andi _rt*, _rs*, _imm* {
  378. print_instr_rimm 'andi', _imm, _rt, _rs
  379. I 12, _rs, _rt, _imm }
  380. macro _ori _rt*, _rs*, _imm* {
  381. print_instr_rimm 'ori', _imm, _rt, _rs
  382. I 13, _rs, _rt, _imm }
  383. macro _xori _rt*, _rs*, _imm* {
  384. print_instr_rimm 'xori', _imm, _rt, _rs
  385. I 14, _rs, _rt, _imm }
  386. ; Load from main memory
  387. macro _lui _rt*, _imm* {
  388. print_instr_rimm 'lui', _imm, _rt
  389. I 15, 0, _rt, _imm }
  390. macro _lb _rt*, _imm=0, _rs* {
  391. print_instr_rrel 'lb', _rt, _imm, _rs
  392. I 32, _rs, _rt, _imm }
  393. macro _lh _rt*, _imm*, _rs* {
  394. print_instr_rrel 'lh', _rt, _imm, _rs
  395. I 33, _rs, _rt, _imm }
  396. macro _lw _rt*, _imm*, _rs* {
  397. print_instr_rrel 'lw', _rt, _imm, _rs
  398. I 34, _rs, _rt, _imm }
  399. macro _lbu _rt*, _imm*, _rs* {
  400. print_instr_rrel 'lbu', _rt, _imm, _rs
  401. I 36, _rs, _rt, _imm }
  402. macro _lhu _rt*, _imm*, _rs* {
  403. print_instr_rrel 'lhu', _rt, _imm, _rs
  404. I 37, _rs, _rt, _imm }
  405. macro _li _rt*, _imm32* {
  406. ; db ' # li '
  407. ; _register_name _rt
  408. ; db ', 0x'
  409. ;if _imm32 <= $FF
  410. ; print_byte _imm32
  411. ;else if _imm32 <= $FFFF
  412. ; print_halfword _imm32
  413. ;else
  414. ; print_word _imm32
  415. ;end if
  416. ; db ' # ',`_imm32
  417. ; db 10
  418. if _imm32 > 0xFFFF
  419. _lui _rt, (_imm32 shr 16)
  420. if (_imm32 and 0xFFFF) > 0
  421. _ori _rt, _rt, (_imm32 and 0xFFFF)
  422. end if
  423. else
  424. _addiu _rt, _zero, _imm32
  425. end if
  426. }
  427. macro _la _rt*, _imm32* {
  428. ; db ' # la '
  429. ; _register_name _rt
  430. ; db ', 0x'
  431. ; print_word _imm32
  432. ; db ' # ',`_imm32
  433. ; db 10
  434. if _imm32 > 0xFFFF
  435. _lui _rt, (_imm32 shr 16)
  436. if (_imm32 and 0xFFFF) > 0
  437. _ori _rt, _rt, (_imm32 and 0xFFFF)
  438. end if
  439. else
  440. _addiu _rt, _zero, _imm32
  441. end if
  442. }
  443. ; Store on main memory
  444. macro _sb _rt*, _imm*, _rs* {
  445. print_instr_rrel 'sb', _rt, _imm, _rs
  446. I 40, _rs, _rt, _imm }
  447. macro _sh _rt*, _imm*, _rs* {
  448. print_instr_rrel 'sh', _rt, _imm, _rs
  449. I 41, _rs, _rt, _imm }
  450. macro _sw _rt*, _imm*, _rs* {
  451. print_instr_rrel 'sw', _rt, _imm, _rs
  452. I 43, _rs, _rt, _imm }
  453. ; SPIM macros
  454. defaultSpace equ _Text
  455. macro _asm text {
  456. db text,10
  457. }
  458. macro _noat {
  459. _asm '.set noat'
  460. }
  461. macro _at {
  462. _asm '.set at'
  463. }
  464. macro _comment text {
  465. db '# ',text,10
  466. }
  467. macro _comment_append text {
  468. store byte ' ' at $-1
  469. db '# ',text,10
  470. }
  471. virtual at 0x00400024
  472. _Text::
  473. end virtual
  474. macro _ttext {
  475. local addr
  476. virtual _Text
  477. addr:
  478. end virtual
  479. _addr = addr
  480. db '.text 0x'
  481. print_word _addr
  482. db 10
  483. purge _addr
  484. defaultSpace equ _Text
  485. }
  486. macro _dtext {
  487. local addr
  488. virtual _Text
  489. addr:
  490. end virtual
  491. _addr = addr
  492. db '.data 0x'
  493. print_word _addr
  494. db 10
  495. purge _addr
  496. defaultSpace equ _Text
  497. }
  498. macro _globl _lbl {
  499. db '.globl ',`_lbl,10
  500. }
  501. virtual at 0x10010000
  502. _Data::
  503. end virtual
  504. macro _ddata {
  505. local addr
  506. virtual _Data
  507. addr:
  508. end virtual
  509. _addr = addr
  510. db '.data 0x'
  511. print_word _addr
  512. db 10
  513. purge _addr
  514. defaultSpace equ _Data
  515. }
  516. macro _word [v] {
  517. common
  518. virtual defaultSpace
  519. forward
  520. dd v
  521. common
  522. end virtual
  523. forward
  524. db ' .word 0x'
  525. print_word v
  526. db 10
  527. }
  528. macro _dw [v] {
  529. _word v
  530. }
  531. macro _half [v] {
  532. common
  533. virtual defaultSpace
  534. forward
  535. dw v
  536. common
  537. end virtual
  538. forward
  539. db ' .half 0x'
  540. print_halfword v
  541. db 10
  542. }
  543. macro _dh [v] {
  544. _half v
  545. }
  546. macro _byte [v] {
  547. common
  548. virtual defaultSpace
  549. forward
  550. db v
  551. common
  552. end virtual
  553. forward
  554. db ' .byte 0x'
  555. print_byte v
  556. db 10
  557. }
  558. macro _db [v] {
  559. _byte v
  560. }
  561. macro _asciiz t {
  562. local last
  563. virtual defaultSpace
  564. db t,0
  565. end virtual
  566. db ' .asciiz "'
  567. db t
  568. load last byte from $-1
  569. if last = 10
  570. store byte '\' at $-1
  571. db 'n'
  572. end if
  573. db '"',10
  574. }
  575. macro _space len {
  576. db '.space 0x'
  577. print_halfword len
  578. db 10
  579. virtual defaultSpace
  580. rb len
  581. end virtual
  582. }
  583. macro _rw len {
  584. _space (len*4)
  585. }
  586. macro _rh len {
  587. _space (len*2)
  588. }
  589. macro _rb len {
  590. _space len
  591. }
  592. macro _label name {
  593. _asm <`name,':'>
  594. virtual defaultSpace
  595. name:
  596. end virtual
  597. }
  598. macro _align expoent {
  599. _asm <'.align ',`expoent>
  600. virtual defaultSpace
  601. align (2 shl (expoent-1))
  602. end virtual
  603. }
  604. ; SPIM syscalls
  605. spim_service:
  606. .puti = 1
  607. .putf = 2
  608. .putd = 3
  609. .puts = 4
  610. .geti = 5
  611. .getf = 6
  612. .getd = 7
  613. .gets = 8
  614. .sbrk = 9
  615. .exit = 10
  616. .putc = 11
  617. .getc = 12
  618. .open = 13
  619. .read = 14
  620. .write = 15
  621. .close = 16
  622. .exit2 = 17
  623. spim_service.filemode.r = 0
  624. spim_service.filemode.w = 1