Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

about half of an ARM assembler in bash

3 views
Skip to first unread message

presidentbyamendment

unread,
May 1, 2012, 7:50:58 PM5/1/12
to
# TARM thumb ARM TARM thumb ARM TARM thumb ARM TARM thumb ARM TARM
thumb ARM


########## internals, and meta-noise like thumb

# wants ../shasm for $bit14, $b11100011, ad, aq, ab...

A=0 B=1 C=2 D=3 E=4 SI=5 DI=6

SP=13 # thumb SP is 13, but we use r7 for internals in jump,
call...
LR=14
PC=15


spsp ( ) { # copy the pa SP to the ARM "SP" prior to pop and such
# mov(3)
ad $(( $bit14 | 3 << 9 | $bit6 | 7 << 3 | 13 ))
}

# wide 2-thumb-insn bl calcs
# mask = $bit11-1 = 2047 = 0x7ff
# 2-insn thumb wide branch and link
BLwide ( ) { # BLwide exact_byte-addr_o/s
# internal macro given o/s for 2 insn bl
# for call, enter...
local HI LO
HI=`rpn $1 1 d 11 d 0x7ff a`
LO=`rpn $1 1 d 0x7ff a`
ad $(( 7 << 13 | 2 << 11 | $HI ))
ad $(( 7 << 13 | 3 << 11 | $LO ))
}



bx2arm ( ) { # jump from here to here, but switch to RISC 32 ARM
insns
### ALIGN for 32 first, yo.
ad $(( $_I___III << 8 | 15 << 3 )) # bx PC, which reads right in
thumb
}



thumb ( ) { ## call this protruberance after ELF to get into pa/
thumb
## well worth it.
## Also used to get out of RISC in e.g. mult
# pc -> lr
aq 0xe1a0e00f # mov lr, pc
# +5 or so to lr to turn on thumb (bit0)
# ARM PC reads 4 bytes too far ahead.
aq 0xe28ee005 # add lr, lr, #5

# bx to there, which is here
aq $(( $b00010010 << 20 | $bit4 | $LR )) # bx LR
}




########### pa-visible pa-visible pa-visible pa-visible pa-
visible pa-visible



= () { # = srcreg destreg mov/copy/clobber
ab $(($1<<3|$2)) 0x1c
}



1+ () { # 1+ reg
ab 1 $((0x30|$1)) # see why I went thumb?
}



1- () { # 1- reg
ab 1 $((0x38|$1))
}



+ () { # + reg destreg
ad $(( $b00001100 << 9 | $1 << 6 | $2 << 3 | $2 ))
}



+byte () { # num destreg sign-ext lit and add to destreg

ad $(( 3<<12 | $2 << 8 | $1 ))
}



+carry () { # +carry src dest
ad $(($bit14 | $bit8 | $bit6 | $1 << 3 | $2 ))
}



- () { # - srcreg destreg d - s -> d
# sub(3)
ad $(( $bit12 | $bit11 | $bit9 | $1 << 6 | $2 << 3 | $2 ))
}



-borrow () { # srcreg destreg

ad $(( $bit14 | 3 << 8 | $1 <<3 | $1 ))
}



AND () { # AND reg destreg
ad $(( $bit14 | $1 << 3 | $2 ))
}



call () { # call imm
# return is pop PC
# Given that, I have a 4 insn call. That's 8, maybe 10 bytes,
plus a
# 32-bit literal. Its worth this monstrosity because ...
# Its not my fault ARM doesn't know how computers work
# its standard jsr/rts semantics
# it's a 32 bit range
# it doesn't require anything in the callee besides
# return
# its as good as RISC ARM, or better
#
# using the ARM thumb SP is OK since it's about names.
# We therefor can use r7 for such things.
# And you can break pa whenever you want.

align 4 # zero sets the Z flag. I'm OK with that.
# offset_past_lit(x4) + PC --> r7
ad $(( $bit15|$bit13| 7<<8 | 3 ))
# push r7
ad 0xb480
# 4 meg bl
ad $(( $bit14 | $bit11 | 7 << 8 | 1 )) # load pc-rel literal 4 bytes
ahead into r7
ad $(( $bit14 | 3 << 9 | $bit7 | 7<<3 | 7 )) # mov(3) r7 to PC
ad 0
aq $1

}



callr () { # callr reg abs. o/s
# with this you can call an execution array.

# offset_past_lit(x4) + PC --> r7
ad $(( $bit15|$bit13| 7<<8 | 1 ))
# push r7
ad 0xb480
ad $(( $bit14 | 3 << 9 | $bit7 | $1<<3 | 7 )) # mov(3) r7 to PC
}



divmod () { # reg ( one arg in A, mod in HIGH, )

}



down () { # reg impl. shift in C
# LSR(2)
ad $(( $bit14 | 3 << 6 | C << 3 | $1 ))
}



downi () { # downi reg imm imm shift byte
# lsr(1)
ad $(( $bit11 | $2 << 6 | $1 << 3 | $1 ))
}



downroll () { # reg bits in C, r

ad $(( $bit14 | 7<<6 | C << 3 | $1 ))
}



downrollc () { # reg bits in C, include carry in roll

ad $(( ))
}



downs () { # downs reg downshift reg by C, sign-fill
high side
ad $(( $bit14 | $bit8 | $C << 3 | $1 ))
}



downwide () { # impl. D=HI E=low C=shift

}



h0bit () { # h0bit countee count count high-side 0 bits
# call RISC?
ad $(( ))
}




jump () { # jump num absolute wide
# load pc-rel
align 4 # zero isn't a strict nop, it just sets Z
ad $(( $bit14 | $bit11 | 7 << 8 | 1 )) # load pc-rel literal 4 bytes
ahead into r7
ad $(( $bit14 | 3 << 9 | $bit7 | 7<<3 | 7 )) # mov(3) r7 to PC
ad 0
aq $1
}



jumpr () { # jumpr reg jump reg. wide abs.
# mov(3) reg to PC
ad $(( $bit14 | 3<<9 | $1 << 3 | $bit7 | 7 ))
}



l () { # l BASE imm5 DEST no imm, give it a 0
# immediate offset is upshifted by 2 by insn
# ldr(1)
ad $(( $b00001101 << 11 | $2 << 6 | $1 <<3 | $3 ))
}



lb () { # lb regb num dest give it a 0 for no offset
# ldrb(1)

ad $(( 15 << 11 | $2 << 6 | $1 <<3 | $3 ))
}



lib () { # lib num reg sign extended on arm?
# mov(1) ambiguous as to extension
ad $(( $bit13 | $2 << 8 | $1 ))
}



lpi () { # load post-incrementing [SI++] --> A int (4) incr
# ldmia
ad $(( $b00011001 << 11 | SI << 8 | 1 ))
}



msxb () { # move and sign-extend byte msxb bytereg dest

ad $(( ))
}



mult () { # mult reg reg * A --> D:A
# switch to RARM for this
bx2arm

thumb
}



neg () { # neg reg
# neg
ad $(( $bit14 | 9 << 6 | $1 << 3 | $1 ))
}



nop () { # --- sets Z flag, but encodes to 0, which I like.
ad 0
}



NOT () { # NOT reg
# MVN
ad $(( $bit14 | 15 << 6 | $1 << 3 | $1 ))
}



OR () { # OR reg dest
# ORR
ad $(( $bit14 | 12 << 6 | $1 <<3 | $2 ))
}



pull () { # pull reg
# pop
ab $(( $b10111100<<8 | 1 << $1 ))
}



push () { # reg
# push
ab $(( $b10110100<<8 | 1 << $1 ))
}



pullem () { # ---

ab $(( $b10111100<<8 | 255 ))
}



pushem () { # ---

ab $(( $b10110100<<8 | 255 ))
}



return () { # --- (framedrop version maybe later
leave)
# pop PC
ad $(( 11<<12 | 1 << 11 | 2 << 9 | $bit8 ))
}



s () { # s sreg addrreg imm give it a 0 if no o/s
# srt(1)
ad $(( $bit14|$bit13 | $3<< 6 | $2 << 3 | $1 ))
}



sb () { # s sreg addrreg imm give it a 0 if no o/s
# strb(1)
ad $(( 7<<12 | $3 << 6 | $2 << 3 | $1 ))
}



spi () { # store post-incrementing A --> [DI+4]!
# stmia
ad $(( $b00011000 << 11 | DI << 8 | 1 ))
}



submit () { # submit IRQ# trap to supervisor. Syscall.

ad $(( $b11011111 << 8 | $1 ))
}



TAND () { # TAND reg reg AND regs for flags only

ad $(( $bit14 | $bit9 | $1 << 3 | $2 ))
}



tsub () { # tsub minuend subtrahend test subtract
# cmp
ad $(( $bit14 | $bit9 | $bit7 | $1 <<3 | $2 ))
}



up () { # up shiftee/dest upshift reg by C, zero-fill
# lsl(2)
ad $(( $bit14 | $bit7 | $C <<3 | $1 ))
}



upi () { # upi imm shiftee/dest
# lsl(1)
ad $(( $1 << 6 | $2 << 3 | $2 ))
}



upwide () { # upshift wide

}



when () { # when CC num [raw] abs(num)<512
local offset

if test $3 ; then
let offset=$3>>1
else
let offset=$(( 255 & ( ($H-$3) >>1 ) )) # don't OR a big neg.
fi
ad $(( $b00001101 << 12 | $1 << 8 | $offset ))
}



XOR () { # XOR srcreg destreg
ad $(( $bit14 | $bit6 | $1 << 3 | $2 ))
}




###########() # plurals etc.

copy () { # move C ints from [SI++] to [DI++]

}



fill () { # fill C copies of int A into [DI++]

}




rangematch () { # compare C ints of [SI++] - [DI++], C=0 if ranges
match

}



find () { # compare C ints from [DI++] against A; C holds count of
1st match

}



findnot () { # compare C ints from [DI++] against A; C holds count
of 1st mismatch

}



sum () { # uses A, C, SI; sum in A

}



xsum () { # uses A, C, SI; sum in A

}



scale () { # reg mult reg * A, downshift double result D:A by C

}



timesdiv () { # arg arg * A double, div double by C Forth
*/

}


#Sun Apr 29 23:47:49 EDT 2012

# Rick arrest Bush deport Obama Hohensee
rick_h...@email.com
# http://presidentbyamendment.com ftp.gwdg.de/pub/cLIeNUX/
interim
# presidentbyamendment on facebook and youtube
# shasm H3sm cLIeNUX libsys.a scale
LAAETTR :o)

# TARM thumb ARM TARM thumb ARM TARM thumb ARM TARM thumb ARM TARM
thumb ARM
0 new messages