Annotation of gforth/arch/mips/asm.fs, revision 1.23
1.21 dvdkhlng 1: \ asm.fs assembler file (for MIPS32)
1.1 anton 2: \
1.23 ! anton 3: \ Copyright (C) 2000,2007,2010 Free Software Foundation, Inc.
1.17 anton 4:
5: \ This file is part of Gforth.
6:
7: \ Gforth is free software; you can redistribute it and/or
8: \ modify it under the terms of the GNU General Public License
1.19 anton 9: \ as published by the Free Software Foundation, either version 3
1.17 anton 10: \ of the License, or (at your option) any later version.
11:
12: \ This program is distributed in the hope that it will be useful,
13: \ but WITHOUT ANY WARRANTY; without even the implied warranty of
14: \ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: \ GNU General Public License for more details.
16:
17: \ You should have received a copy of the GNU General Public License
1.19 anton 18: \ along with this program. If not, see http://www.gnu.org/licenses/.
1.1 anton 19:
1.8 anton 20: \ test this with
1.21 dvdkhlng 21: \
22: \ ./gforth -i kernl64l.fi exboot.fs startup.fs \
23: \ arch/mips/{asm.fs,disasm.fs,insts.fs} \
24: \ -e "also assembler here" arch/mips/testasm.fs
25: \ -e "here over - here" arch/mips/testdisasm.fs
26: \ -e "here over - compare throw bye"
27: \
28: \ This test should also work when run on non-mips systems. Even on 64-bit
29: \ systems. the mips assembler is 64-bit safe, so you can use it to
30: \ cross-compile e.g. from an AMD64 target.
1.8 anton 31:
1.16 anton 32: require ./../../code.fs
1.4 anton 33:
1.7 anton 34: get-current
1.4 anton 35: also assembler definitions
36:
1.1 anton 37: $20 constant asm-registers
38:
1.3 anton 39: \ register names
40: 0 constant $zero
41: 1 constant $at
42: 2 constant $v0
43: 3 constant $v1
44: \ 4 constant $a0 \ commented out to avoid shadowing hex numbers
45: \ 5 constant $a1
46: \ 6 constant $a2
47: \ 7 constant $a3
48: 8 constant $t0
49: 9 constant $t1
50: 10 constant $t2
51: 11 constant $t3
52: 12 constant $t4
53: 13 constant $t5
54: 14 constant $t6
55: 15 constant $t7
56: 16 constant $s0
57: 17 constant $s1
58: 18 constant $s2
59: 19 constant $s3
60: 20 constant $s4
61: 21 constant $s5
62: 22 constant $s6
63: 23 constant $s7
64: 24 constant $t8
65: 25 constant $t9
66: 26 constant $k0
67: 27 constant $k1
68: 28 constant $gp
69: 29 constant $sp
70: 30 constant $s8
71: 31 constant $ra
1.1 anton 72:
1.22 dvdkhlng 73: $00 constant #asm-special
74: $1C 26 lshift constant #asm-special2
1.1 anton 75:
1.3 anton 76: $1F constant asm-bm05
77: $3F constant asm-bm06
78: $FFFF constant asm-bm10
79: $3FFFFFF constant asm-bm1A
1.1 anton 80:
1.21 dvdkhlng 81: : l, here 4 allot l! ;
82:
1.1 anton 83: : asm-op ( n -- code )
84: asm-bm06 and $1a lshift ;
85:
1.8 anton 86: : check-range ( u1 u2 u3 -- )
87: within 0= -24 and throw ;
88:
89: : asm-rs ( u code -- code )
90: over 0 $20 check-range
91: swap $15 lshift or ;
1.1 anton 92:
93: : asm-rt ( n code -- code )
1.8 anton 94: over 0 $20 check-range
95: swap $10 lshift or ;
1.1 anton 96:
97: : asm-imm ( n code -- code )
1.8 anton 98: over -$8000 $8000 check-range
99: swap $ffff and or ;
1.1 anton 100: ' asm-imm alias asm-offset
101:
1.8 anton 102: : asm-uimm ( u code -- code )
103: over 0 $10000 check-range
104: or ;
105:
106: : asm-rel ( n code -- code )
107: over 3 and 0<> -24 and throw \ check lower 2 bits
108: swap 2/ 2/ swap asm-imm ;
109:
1.1 anton 110: : asm-target ( n code -- code )
1.21 dvdkhlng 111: over here 4 + xor $f0000003 and 0<> -24 and throw
1.1 anton 112: swap 2 rshift asm-bm1A and or ;
113:
114: : asm-rd ( n code -- code )
1.8 anton 115: over 0 $20 check-range
116: swap $b lshift or ;
1.1 anton 117:
118: : asm-shamt ( n code -- code )
1.8 anton 119: over 0 $20 check-range
120: swap $6 lshift or ;
1.1 anton 121: ' asm-shamt alias asm-sa
122:
123: : asm-funct ( n code -- code )
124: swap asm-bm06 and or ;
125:
1.3 anton 126: : asm-special ( code1 -- code2 )
1.22 dvdkhlng 127: #asm-special asm-funct ;
1.21 dvdkhlng 128:
129: : asm-special2 ( code1 -- code2 )
1.22 dvdkhlng 130: #asm-special2 asm-funct ;
1.3 anton 131:
1.1 anton 132: \ ***** I-types
1.3 anton 133: : asm-I-rt,imm ( code -- )
134: create ,
135: does> ( rt imm -- )
1.21 dvdkhlng 136: @ asm-imm asm-rt l, ;
1.3 anton 137:
1.7 anton 138: : asm-I-rt,uimm ( code -- )
139: create ,
140: does> ( rt uimm -- )
1.21 dvdkhlng 141: @ asm-uimm asm-rt l, ;
1.7 anton 142:
1.3 anton 143: : asm-I-rs,imm ( code -- )
144: create ,
145: does> ( rs imm -- )
1.21 dvdkhlng 146: @ asm-rel asm-rs l, ;
1.3 anton 147:
148: : asm-I-rt,rs,imm ( code -- )
149: create ,
150: does> ( rt rs imm -- )
1.21 dvdkhlng 151: @ asm-imm asm-rs asm-rt l, ;
1.3 anton 152:
1.7 anton 153: : asm-I-rt,rs,uimm ( code -- )
154: create ,
155: does> ( rt rs uimm -- )
1.21 dvdkhlng 156: @ asm-uimm asm-rs asm-rt l, ;
1.7 anton 157:
1.3 anton 158: : asm-I-rs,rt,imm ( code -- )
159: create ,
160: does> ( rs rt imm -- )
1.21 dvdkhlng 161: @ asm-rel asm-rt asm-rs l, ;
1.3 anton 162:
163: : asm-I-rt,offset,rs ( code -- )
164: create ,
165: does> ( rt offset rs -- )
1.21 dvdkhlng 166: @ asm-rs asm-offset asm-rt l, ;
1.1 anton 167:
168: \ ***** regimm types
169: : asm-regimm-rs,imm ( funct -- )
170: $01 asm-op asm-rt asm-I-rs,imm ;
171:
172: \ ***** copz types 1
173:
1.3 anton 174: : asm-I-imm,z ( code -- )
175: create ,
176: does> ( imm z -- )
1.21 dvdkhlng 177: @ swap asm-op or asm-rel l, ;
1.1 anton 178:
179: : asm-copz-imm ( code -- )
180: $10 asm-op or asm-I-imm,z ;
181:
1.3 anton 182: : asm-I-rt,offset,rs,z ( code -- )
183: create ,
184: does> ( rt offset rs z -- )
1.21 dvdkhlng 185: @ swap asm-op or asm-rs asm-offset asm-rt l, ;
1.1 anton 186:
187: : asm-copz-rt,offset,rs ( code -- )
188: asm-op asm-I-rt,offset,rs,z ;
189:
1.3 anton 190: : asm-J-target ( code -- )
191: create ,
192: does> ( target -- )
1.21 dvdkhlng 193: @ asm-target l, ;
1.1 anton 194:
195: \ ***** special types
1.3 anton 196: : asm-special-nothing ( code -- )
197: asm-special create ,
198: does> ( addr -- )
1.21 dvdkhlng 199: @ l, ;
1.3 anton 200:
201: : asm-special-rd ( code -- )
202: asm-special create ,
203: does> ( rd addr -- )
1.21 dvdkhlng 204: @ asm-rd l, ;
1.3 anton 205:
206: : asm-special-rs ( code -- )
207: asm-special create ,
208: does> ( rs addr -- )
1.21 dvdkhlng 209: @ asm-rs l, ;
1.3 anton 210:
211: : asm-special-rd,rs ( code -- )
212: asm-special create ,
213: does> ( rd rs addr -- )
1.21 dvdkhlng 214: @ asm-rs asm-rd l, ;
1.3 anton 215:
216: : asm-special-rs,rt ( code -- )
217: asm-special create ,
218: does> ( rs rt addr -- )
1.21 dvdkhlng 219: @ asm-rt asm-rs l, ;
1.3 anton 220:
221: : asm-special-rd,rs,rt ( code -- )
222: asm-special create ,
223: does> ( rd rs rt addr -- )
1.21 dvdkhlng 224: @ asm-rt asm-rs asm-rd l, ;
1.3 anton 225:
226: : asm-special-rd,rt,rs ( code -- )
227: asm-special create ,
228: does> ( rd rt rs addr -- )
1.21 dvdkhlng 229: @ asm-rs asm-rt asm-rd l, ;
1.3 anton 230:
231: : asm-special-rd,rt,sa ( code -- )
232: asm-special create ,
233: does> ( rd rt sa addr -- )
1.21 dvdkhlng 234: @ asm-sa asm-rt asm-rd l, ;
1.1 anton 235:
1.21 dvdkhlng 236: : asm-special2-rd,rs ( code -- )
237: asm-special2 create ,
238: does> ( rd rs addr -- ) \ note: rt equal rd for these special2 opcodes!
239: @ asm-rs over swap asm-rd asm-rt l, ;
240:
241: : asm-special2-rs,rt ( code -- )
242: asm-special2 create ,
243: does> ( rs rt addr -- )
244: @ asm-rt asm-rs l, ;
245:
246: : asm-special2-rd,rs,rt ( code -- )
247: asm-special2 create ,
248: does> ( rd rs rt addr -- )
249: @ asm-rt asm-rs asm-rd l, ;
250:
1.1 anton 251: \ ***** copz types 2
252: : asm-copz0 ( funct -- )
1.3 anton 253: $10 $10 asm-op asm-rs asm-funct create ,
254: does> ( addr -- )
1.21 dvdkhlng 255: @ l, ;
1.1 anton 256:
257: : asm-copz-rt,rd ( funct -- )
1.3 anton 258: $10 asm-op or create ,
259: does> ( rt rd z addr -- )
1.21 dvdkhlng 260: @ swap asm-op or asm-rd asm-rt l, ;
1.1 anton 261:
262: : nop, ( -- )
1.21 dvdkhlng 263: 0 l, ;
1.1 anton 264:
1.5 anton 265: include ./insts.fs
1.1 anton 266:
267: : move, ( rd rs -- )
1.3 anton 268: $zero addu, ;
1.1 anton 269:
1.9 anton 270: \ commented out to reduce delay slot exceptions
271: \ : abs, ( rd rs -- )
272: \ dup $0008 bgez,
273: \ 2dup move,
274: \ $zero swap subu, ;
1.1 anton 275:
276: : neg, ( rd rs -- )
1.3 anton 277: $zero swap subu, ;
1.1 anton 278:
279: : negu, ( rd rs -- )
1.3 anton 280: $zero swap subu, ;
1.1 anton 281:
282: : not, ( rd rs -- )
1.3 anton 283: $zero nor, ;
1.1 anton 284:
285: : li, ( rd imm -- )
286: dup 0= if
1.3 anton 287: drop dup $zero = if
1.1 anton 288: drop nop, assert( false )
289: else
1.3 anton 290: $zero move,
1.1 anton 291: endif
292: else
293: dup $8000 u< if
1.3 anton 294: $zero swap addiu,
1.1 anton 295: else
296: dup $10000 u< if
1.3 anton 297: $zero swap ori,
1.1 anton 298: else
299: dup $ffff and 0= if
300: $10 rshift lui,
301: else
302: dup $ffff8000 and $ffff8000 = if
1.3 anton 303: $zero swap addiu,
1.1 anton 304: else
305: 2dup $10 rshift lui,
306: over swap ori,
307: endif
308: endif
309: endif
310: endif
311: endif ;
312:
313: : blt, ( rs rt imm -- ) \ <
1.3 anton 314: >r $at rot rot slt,
315: $at $zero r> bne, ;
1.1 anton 316:
317: : ble, ( rs rt imm -- ) \ <=
1.3 anton 318: >r $at rot rot swap slt,
319: $at $zero r> beq, ;
1.1 anton 320:
321: : bgt, ( rs rt imm -- ) \ >
1.3 anton 322: >r $at rot rot swap slt,
323: $at $zero r> bne, ;
1.1 anton 324:
325: : bge, ( rs rt imm -- ) \ >=
1.3 anton 326: >r $at rot rot slt,
327: $at $zero r> beq, ;
1.1 anton 328:
329: : bltu, ( rs rt imm -- ) \ < unsigned
1.3 anton 330: >r $at rot rot sltu,
331: $at $zero r> bne, ;
1.1 anton 332:
333: : bleu, ( rs rt imm -- ) \ <= unsigned
1.3 anton 334: >r $at rot rot swap sltu,
335: $at $zero r> beq, ;
1.1 anton 336:
337: : bgtu, ( rs rt imm -- ) \ > unsigned
1.3 anton 338: >r $at rot rot swap sltu,
339: $at $zero r> bne, ;
1.1 anton 340:
341: : bgeu, ( rs rt imm -- ) \ >= unsigned
1.3 anton 342: >r $at rot rot sltu,
343: $at $zero r> beq, ;
1.9 anton 344:
345: \ control structures
346:
347: \ conditions; they are reversed because of the if and until logic (the
348: \ stuff enclosed by if is performed if the branch around has the
1.10 anton 349: \ inverse condition, cf. 0branch).
1.9 anton 350:
351: ' beq, constant ne
352: ' bne, constant eq
353: ' blez, constant gtz
354: ' bgtz, constant lez
355: ' bltz, constant gez
356: ' bgez, constant ltz
1.13 anton 357: \ bczf, bczt, \ these don't take the relative address as last argument
1.9 anton 358: ' blt, constant ge
359: ' ble, constant gt
360: ' bgt, constant le
361: ' bge, constant lt
362: ' bltu, constant geu
363: ' bleu, constant gtu
364: ' bgtu, constant leu
365: ' bgeu, constant ltu
366:
1.10 anton 367: \ an asm-cs-item consists of ( addr magic1 magic2 ). addr is the
368: \ address behind the branch or the destination. magic2 is LIVE-ORIG or
369: \ DEST xored with asm-magic to make it harder to confuse with a
370: \ register number or immediate value. magic1 is LIVE-orig or DEST.
371: \ It's there to make CS-ROLL etc. work.
1.9 anton 372:
1.10 anton 373: : magic-asm ( u1 u2 -- u3 u4 )
1.9 anton 374: \ turns a magic number into an asm-magic number or back
375: $87654321 xor ;
376:
1.10 anton 377: : patch-branch ( branch-delay-addr target-addr -- )
378: \ there is a branch just before branch-delay-addr; PATCH-BRANCH
379: \ patches this branch to branch to target-addr
380: over - ( branch-delay-addr rel )
1.21 dvdkhlng 381: swap 4 - dup >r ( rel branch-addr R:branch-addr )
382: ul@ asm-rel r> l! ; \ !! relies on the imm field being 0 before
1.10 anton 383:
1.9 anton 384: : if, ( ... xt -- asm-orig )
385: \ xt is for a branch word ( ... addr -- )
386: 0 swap execute
1.10 anton 387: here live-orig magic-asm live-orig ;
1.9 anton 388:
389: : ahead, ( -- asm-orig )
390: $zero $zero ne if, ;
391:
392: : then, ( asm-orig -- )
1.10 anton 393: orig? magic-asm orig?
394: here patch-branch ;
395:
396: : begin, ( -- asm-dest )
397: here dest magic-asm dest ;
398:
399: : until, ( asm-dest ... xt -- )
400: \ xt is a condition and ... are its arguments
401: 0 swap execute
402: dest? magic-asm dest?
403: here swap patch-branch ;
404:
405: : again, ( asm-dest -- )
406: $zero $zero ne until, ;
407:
408: : while, ( asm-dest -- asm-orig asm-dest )
409: if, 1 cs-roll ;
410:
1.11 anton 411: : delayed-then, ( asm-orig -- )
412: \ set the target of asm-orig to one instruction after the current one
1.21 dvdkhlng 413: 0 l, then, -4 allot ;
1.11 anton 414:
415: : else, ( asm-orig1 -- asm-orig2 )
416: ahead, 1 cs-roll delayed-then, ;
417:
1.10 anton 418: : repeat, ( asm-orig asm-dest -- )
1.11 anton 419: again, delayed-then, ;
1.1 anton 420:
1.12 anton 421: : endif, ( asm-orig -- )
422: then, ;
423:
1.4 anton 424: previous
1.10 anton 425: set-current
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>