blob: 692bd5d5a834686348f28ede477ded082dfa22a9 [file] [log] [blame]
#
# linux_logo in ppc assembly language
# based on the code from ll_asm-0.36
#
# By Vince Weaver <vince _at_ deater.net>
#
# Modified to remove non-deterministic system calls
# And to avoid reading from /proc
#
# offsets into the results returned by the uname syscall
.equ U_SYSNAME,0
.equ U_NODENAME,65
.equ U_RELEASE,65*2
.equ U_VERSION,(65*3)
.equ U_MACHINE,(65*4)
.equ U_DOMAINNAME,65*5
# offset into the SYSCALL_SYSINFO buffer
.equ S_TOTALRAM,16
# Sycscalls
.equ SYSCALL_EXIT, 1
#.equ SYSCALL_READ, 3
.equ SYSCALL_WRITE, 4
#.equ SYSCALL_OPEN, 5
#.equ SYSCALL_CLOSE, 6
#.equ SYSCALL_SYSINFO,116
#.equ SYSCALL_UNAME, 122
#
.equ STDIN, 0
.equ STDOUT,1
.equ STDERR,2
.equ BSS_BEGIN,25
.equ DATA_BEGIN,26
.include "logo.include"
.globl _start
_start:
#========================
# Initialization
#========================
# eieio # coolest opcode of all time ;)
# not needed, but I had to put it here
# the hack loading BSS_BEGIN and DATA_BEGIN
# saves one instruction on any future load from memory
# as we can just do an addi rather than an lis;addi
lis 25,bss_begin@ha
addi 25,25,bss_begin@l
lis 26,data_begin@ha
addi 26,26,data_begin@l
addi 14,BSS_BEGIN,(out_buffer-bss_begin)
# the output buffer
addi 21,BSS_BEGIN,(text_buf-bss_begin)
mr 17,14 # store out-buffer for later
#=========================
# PRINT LOGO
#=========================
# LZSS decompression algorithm implementation
# by Stephan Walter 2002, based on LZSS.C by Haruhiko Okumura 1989
# optimized some more by Vince Weaver
li 8,(N-F) # grab "R"
addi 9,DATA_BEGIN,(logo-data_begin)-1
# logo_pointer
addi 12,DATA_BEGIN,(logo_end-data_begin)-1
# end of the logo
mr 16,17
decompression_loop:
lbzu 10,1(9) # load in a byte
# auto-update
mr 11,10 # copy to 11
ori 11,11,0xff00 # re-load top as a hackish
# 8-bit counter
test_flags:
cmpw 0,12,9 # have we reached the end?
ble done_logo # ! if so exit
andi. 13,11,0x1
srawi 11,11,1
bne 0,discrete_char
offset_length:
lbzu 10,1(9)
lbzu 24,1(9)
slwi 24,24,8
or 24,24,10
mr 10,24
srawi 15,10,P_BITS
addi 15,15,THRESHOLD+1 # cl = ax >> (P_BITS)+THRESH+1
# = match length
output_loop:
andi. 24,24,(POSITION_MASK<<8+0xff) # mask it
lbzx 10,21,24
addi 24,24,1
store_byte:
stbu 10,1(16)
stbx 10,21,8
addi 8,8,1
andi. 8,8,(N-1)
addic. 15,15,-1
bne 0,output_loop
andi. 13,11,0xff00
bne test_flags
b decompression_loop
discrete_char:
lbzu 10,1(9)
li 15,1
b store_byte
done_logo:
addi 4,17,1 # restore (plus one because r17 is decremented)
bl write_stdout # and print the logo
#==========================
# First Line
#==========================
#==========================
# PRINT VERSION
#==========================
# li 0,SYSCALL_UNAME # uname syscall
# addi 3,BSS_BEGIN,(uname_info-bss_begin)
# uname struct
# sc # do syscall
addi 16,DATA_BEGIN,(uname_info-data_begin)+U_SYSNAME@l-1
# os-name from uname "Linux"
bl strcat
addi 16,DATA_BEGIN,(ver_string-data_begin)-1
# source is " Version "
bl strcat
addi 16,DATA_BEGIN,(uname_info-data_begin)+U_RELEASE@l-1
# version from uname "2.4.1"
bl strcat
addi 16,DATA_BEGIN,(compiled_string-data_begin)-1
# source is ", Compiled "
bl strcat
addi 16,DATA_BEGIN,(uname_info-data_begin)+U_VERSION-1
# compiled date
bl strcat
bl center_and_print # write it to screen
#===============================
# Middle-Line
#===============================
#=========
# Load /proc/cpuinfo into buffer
#=========
# li 0,SYSCALL_OPEN # open()
# addi 3,DATA_BEGIN,(cpuinfo-data_begin)
# '/proc/cpuinfo'
# li 4,0 # O_RDONLY <bits/fcntl.h>
# sc # syscall. fd in r0.
# we should check that r0>=0
# mr 13,3 # save fd in r13
# li 0,SYSCALL_READ # read
# addi 4,BSS_BEGIN,(disk_buffer-bss_begin)
# li 5,4096 # 4096 is maximum size of proc file ;)
# sc
# mr 3,13 # restore fd
# li 0,6 # close
# sc
#=============
# Number of CPUs
#=============
mr 14,17 # point output to out_buf
# Assume 1 CPU for now
# my iBook's /proc/cpuinfo does not have a "processor" line ???
addi 16,DATA_BEGIN,(one-data_begin)-1
bl strcat
#=========
# MHz
#=========
lis 20,('l'<<8)+'o' # find 'lock ' and grab up to M
addi 20,20,('c'<<8)+'k'
li 23,'M'
bl find_string
addi 16,DATA_BEGIN,(megahertz-data_begin)-1
# print 'MHz '
bl strcat
#=========
# Chip Name
#=========
lis 20,('c'<<8)+'p' # find 'cpu\t: ' and grab up to \n
addi 20,20,('u'<<8)+'\t'
li 23,'\n'
bl find_string
addi 16,DATA_BEGIN,(comma-data_begin)-1
# print ', '
bl strcat
#========
# RAM
#========
# li 0,SYSCALL_SYSINFO # sysinfo() syscall
# addi 3,BSS_BEGIN,(sysinfo_buff-bss_begin)
# sysinfo_buffer
# sc
lwz 4,(sysinfo_buff+S_TOTALRAM-data_begin)(DATA_BEGIN)
# load bytes of RAM into r4
srawi 4,4,20 # divide by 2^20 to get MB
li 5,0
bl num_to_ascii
addi 16,DATA_BEGIN,(ram_comma-data_begin)-1
# print 'M RAM, '
bl strcat
#========
# Bogomips
#========
lis 20,('m'<<8)+'i' # find 'mips' and grab up to \n
addi 20,20,('p'<<8)+'s'
li 23,'\n'
bl find_string
addi 16,DATA_BEGIN,(bogo_total-data_begin)-1
# print "Bogomips Total"
bl strcat
bl center_and_print # center it
#=================================
# Print Host Name
#=================================
mr 14,17 # restore out buffer
addi 16,DATA_BEGIN,((uname_info-data_begin)+U_NODENAME)-1
# hostname
bl strcat
bl center_and_print
#================================
# Exit
#================================
exit:
li 3,0 # 0 exit value
li 0,SYSCALL_EXIT # put the exit syscall number in eax
sc # and exit
#=================================
# FIND_STRING
#=================================
# r23 is char to end at
# r20 is the 4-char ascii string to look for
# r14 points at output buffer
# r16,r21
find_string:
addi 16,DATA_BEGIN,(disk_buffer-data_begin)-1
# look in cpuinfo buffer
# -1 so we can use lbzu
find_loop:
lwzu 13,1(16) # load in 32 bits, incrementing 8bits
cmpwi 13,0 # ! if null, we are done
beq done
cmpw 13,20 # compare with out 4 char string
bne find_loop # ! if no match, keep looping
# ! if we get this far, we matched
li 21,':'
find_colon:
lbzu 13,1(16) # repeat till we find colon
cmpwi 13,0
beq done
cmpw 13,21
bne find_colon
addi 16,16,1 # skip a char [should be space]
store_loop:
lbzu 13,1(16)
cmpwi 13,0
beq done
cmpw 13,23 # is it end string?
beq almost_done # ! if so, finish
stbu 13,1(14) # ! if not store and continue
b store_loop
almost_done:
li 13,0 # replace last value with null
stb 13,1(14)
done:
blr
#================================
# strcat
#================================
# r13 = "temp"
# r16 = "source"
# r14 = "destination"
strcat:
lbzu 13,1(16) # load a byte from [r16]
stbu 13,1(14) # store a byte to [r14]
cmpwi 13,0 # is it zero?
bne strcat # ! if not loop
subi 14,14,1 # point to one less than null
blr # return
#==============================
# center_and_print
#==============================
# r14 is end of buffer
# r17 is start of buffer
# r29 = saved link register
# r4-r10, r19-r22, r30 trashed
center_and_print:
mflr 29 # back up return address
subf 5,17,14 # see how long the output
# buffer is
cmpwi 5,80 # see if we are >80
bgt done_center # ! if so, bail
li 4,80 # 80 column screen
subf 4,5,4 # subtract strlen
srawi 23,4,1 # divide by two
lis 4,escape@ha
addi 4,4,escape@l
bl write_stdout
mr 4,23
li 5,1 # print to stdout
bl num_to_ascii # print number
lis 4,c@ha
addi 4,4,c@l
bl write_stdout
done_center:
addi 4,17,1 # move string to output+1
bl write_stdout # call write stdout
lis 4,linefeed@ha
addi 4,4,linefeed@l
mtlr 29 # restore link register
# and let write_stdout
# return for us
#================================
# WRITE_STDOUT
#================================
# r4 has string
# r0,r3,r4,r5,r6 trashed
write_stdout:
li 0,SYSCALL_WRITE # write syscall
li 3,STDOUT # stdout
li 5,0 # string length counter
strlen_loop:
lbzx 6,4,5 # get byte from (r4+r5)
addi 5,5,1 # increment counter
cmpi 0,6,0 # is it zero?
bne strlen_loop # ! if not keep counting
addi 5,5,-1
sc # syscall
blr # return
##############################
# Num to Ascii
##############################
# num is in r4
# r5 =0 then strcat, otherwise stdout
# r5-r10,r19,r20,r21,r22,r30 trashed
num_to_ascii:
mflr 30 # save the link register
addi 16,BSS_BEGIN,(num_to_ascii_end-bss_begin)
# the end of a backwards growing
# 10 byte long buffer.
li 20,10 # we will divide by 10
mr 19,4 # load in the value passed
div_by_10:
divw 21,19,20 # divide r19 by r20 put into r21
mullw 22,21,20 # find remainder. 1st q*dividend
subf 22,22,19 # then subtract from original = R
addi 22,22,0x30 # convert remainder to ascii
stbu 22,-1(16) # Store to backwards buffer
mr 19,21 # move Quotient as new dividend
cmpwi 19,0 # was quotient zero?
bne div_by_10 # ! if not keep dividing
write_out:
cmpwi 5,0 # ! if r5 is 0 then skip ahead
bne stdout_num
addi 16,16,-1 # point to the beginning
bl strcat # and strcat it
mtlr 30 # restore link register
blr # return
stdout_num:
mr 4,16 # point to our buffer
mtlr 30 # restore link register
b write_stdout # stdout will return for us
#===========================================================================
.data
#===========================================================================
data_begin:
.include "logo.lzss_new"
ver_string: .ascii " Version \0"
compiled_string: .ascii ", Compiled \0"
megahertz: .ascii "MHz PPC \0"
.equ space, ram_comma+6
.equ comma, ram_comma+5
linefeed: .ascii "\n\0"
escape: .ascii "\033[\0"
c: .ascii "C\0"
ram_comma: .ascii "M RAM, \0"
bogo_total: .ascii " Bogomips Total\0"
default_colors: .ascii "\033[0m\n\n\0"
cpuinfo: .ascii "/proc/cpuinfo\0"
one: .ascii "One \0"
disk_buffer:
.ascii "processor : 0\n"
.ascii "cpu : 745/755\n"
.ascii "temperature : 22-24 C (uncalibrated)\n"
.ascii "clock : 600.000000MHz\n"
.ascii "revision : 51.17 (pvr 0008 3311)\n"
.ascii "bogomips : 49.79\n"
.ascii "timebase : 24960000\n"
.ascii "platform : PowerMac\n"
.ascii "model : PowerBook4,1\n"
.ascii "machine : PowerBook4,1\n"
.ascii "motherboard : PowerBook4,1 MacRISC2 MacRISC Power Macintosh\n"
.ascii "detected as : 257 (iBook 2)\n"
.ascii "pmac flags : 0000001b\n"
.ascii "L2 cache : 256K unified\n"
.ascii "pmac-generation : NewWorld\n\0"
uname_info:
.ascii "Linux\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
.ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
.ascii "henparma\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
.ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
.ascii "2.6.29\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
.ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
.ascii "#1 Wed May 13 15:51:54 UTC 2009\0"
.ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
.ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
.ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
.ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
.ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
sysinfo_buff:
.long 0,0,0,0,512*1024*1024,0,0,0
#============================================================================
#.bss
#============================================================================
.lcomm bss_begin,0
.lcomm num_to_ascii_buff,10
.lcomm num_to_ascii_end,1
.lcomm text_buf, (N+F-1) # These buffers must follow each other
.lcomm out_buffer,16384