home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-07-28 | 42.8 KB | 1,313 lines |
- Last changes made on 28-Sep-91 Version 0.99b
-
- #### # #### ##### #####
- # # # # # # # The Clarke Assembler
- # # ###### #### ####
- # # # # # # # (C)1991 Lutz Vieweg
- #### ##### # # ##### #####
-
- ------------------ Manual ------------------------
-
- 0 Preface
- ---------
-
- Please excuse linguistic mistakes in this text. English is not
- my native language. If you are not great at english, enjoy the
- easy words that are used, if your native language is english,
- think of what would be if you had to translate this text from
- german...
-
- All the text following is up-to-date only at 27th of April 1991.
- The research goes on and on, there may be mistakes, the hardware
- may change.... etc.
-
- This manual is written for people who have some experience in
- programming assembler on any computer. The HP48sx is not the
- right processor to learn assembler.
-
- Of course there are NO (0.00, zero) warranties that there's one
- single true word in this text. Your Monitor may blow up while
- you read it, your grand-ma may die instantly having taken a spot
- on it, I cannot take responsibility on anything that happenes
- with this text.
-
- 1.0 The Clarke-CPU Architecture
- -------------------------------
-
- The Clarke processor is a child of the "Saturn" processor family.
- The Saturn processor family is a rather old one. As far as I know
- it was first used in HP's 71, later modified and customized for usage
- in the HP19B, 28C, 28S, 10B, 20S, 21S and finally 48sx.
-
- 1.1 The Saturn-CPU's characteristics
- ------------------------------------
-
- - CMOS technology (low power consumption)
- - 4 bit data-bus (memory organized in nibbles)
- - 20 bit adress-bus (able to adress 1 mega-nibble = 512kB unpaged)
- - Micro-code based instruction-set
- - 4 not-omni-purpose 64-bit data-registers (called a,b,c,d)
- - 5 64-bit "scratch"-registers (called r0,r1,r2,r3,r4)
- - 2 20-bit adress-registers (called d0,d1)
- - one 4-bit "field-pointer" register (called p)
- - one 20-bit program counter
- - 8-level return-adress stack, 20-bit each level
- - one 16-bit status-register (called st)
- - one 4-bit hardware-status-register (called hst)
- - one 16-bit I/O input-register (called in)
- - one 12-bit I/O output-register (called out)
- - a carry flag
- - operating in either HEX-mode or DEC-mode
-
- 1.2 Clarke-specific features
- ----------------------------
-
- The Clarke processor runs up to 2000000 cycles per second. Actually,
- the processor-clock runs at a speed of about 1,96 MHz in the HP48sx.
- There has been some new instructions implemented in the processor's
- micro-code, compared to the 28s' CPU:
-
- RSI
- MOVE.dd #$xxx,a (needs more nibbles than MOVE.dd #$xxx,c !)
- MOVE.fs|a a|c,rx
- MOVE.fs|a rx,a|c
- EXG.fs|a a|c,rx
- ADD.fs|a #$x,a|b|c|d
- SUB.fs|a #$x,a|b|c|d
- LSR.fs|a #1,a|b|c|d
- BCLR #$x,a|c
- BSET #$x,a|c
- BBC #$x,a|c,label
- BBS #$x,a|c,label
- JMP (a)
- JMP a|c
- move.a pc,a|c
- exg.a a|c,pc
- BUSCD
-
- 1.3 Register usage
- ------------------
-
- The data-registers are the ones that are used to hold values,
- do arithmetics on them or move them elsewhere. There is some
- kind of hierarchy between the four registers, because it is not
- possible to do the same instructions on each of them as it
- is at the 680xx-family's data-registers. From "good" to "bad"
- this hierarchy is c,a,b,d. There are a lot of adressing modes
- available only to the c or a register...
-
- There are no differences in the way the processor supports
- each of the five "scratch"-registers. I set the quotation marks
- because these registers a very important for machine-language
- programmers even if they are supposed to hold "scratch" due to
- their name.
-
- The two adress-registers are also equivalent, they are used to
- hold the adress of any location you want to access in the
- memory. Note that there is no "absolute" adressing possibility
- if want to move data around the memory.
-
- The p register is not found similar on other machines. The normal
- usage of this register will be clear if you look at the "size
- extensions" chapter. But you can use this register also to hold
- one nibble of any kind of data. There are some strange adressing
- modes using this register. Because of it's meaning to the
- move.dd #expr,a.p|c.p instruction it is usually reset to zero
- after it has been changed and used.
-
- The program-counter does not need to be discussed here. It just
- holds the adress were execution takes place actually.
-
- The stack is much to small!!!! I really don't know how people
- can wish to save sillicium by sizing the stack to 8*20 bit.
- You'll have to place your own software-handled stack into memory
- when you wish to run complex machine-language programs.
-
- The status register consists of 16 bit, which are used by the
- operating-system to hold important flags.
-
- The hardware-status-register consists of four bit, having the
- following meanings:
- Bit 0 XM Module missing (set by opcode $00, "empty memory")
- Bit 1 SB Sticky bit (used as some sort of carry for shifting operations)
- Bit 2 SR Service request (set if an I/O device needs "service")
- Bit 3 MP Module pulled (really don't know the sense of this bit yet)
-
- The input and output registers are used to transfer data from and
- to "devices" that are connected "daisy-chained" to the I/O bus.
- I guess HP has decided to keep this chain rather short, at the
- HP48sx I know only two devices accessed via I/O registers
- (piezo-beeper and keyboard), and they are using memory-register
- based I/O in the 48sx as it is done in most computers...
-
- The carry-flag is the only conventional flag that exist in the Clarke
- CPU. It is used as on any other processor I know...
-
-
- 2.0 The CLASS Assembler's Mnemonics
- -----------------------------------
-
- The mnemonics used by the CLASS-Assembler do not equal those published
- by HP in the IDS-manual. HP's mnemonics were a real horror to every
- guy who had programmed machine-language once before. I decided to
- use mnemonics that are similar to the ones used by the 680xx-family
- Assemblers. This is not the same as the BABEL command-set used by
- some former assemblers, but I did not like to use this one because
- I think it is rather inconsequent structured. You may define macros
- to make BABEL source-codes processable CLASS.
-
- A typical CLASS source-line looks like this:
-
- label mnemonic.size parameter,parameter,parameter ; comment
-
- where label is a typical assembler-label which can be of any lenght
- up to 32767 bytes. Of course, the label should not be equal to any
- register- or other special name.
-
- Mnemonic is just the command that should be translated into machine-code,
- with respect to the following size and/or parameters.
-
- The size plays a very important role at the Clarke-processors machine
- language. There are a lot of possible sizes available, but they are
- of course not available to any opcode/adressing mode combination.
-
- 2.1 Size extensions:
- --------------------
-
- The great variety of possible size-extensions seems confusing and
- often useless. But remember, the Saturn-architecture was developed
- to laborate with 64-Bit BCD encoded floating-point-values, and
- therefore the size-extensions really make sense.
-
- .1, .2, .3, .... .16
- A size extension that consists of a decimal number in the range from
- one to sixteen gives just the number of nibbles to be processed by
- the opcode. There are only a few commands that can handle one to
- sixteen nibbles, but this size extension is also used by some
- pseudo-opcodes described later.
- This size extension type will be abbreviated '.dd' in the following.
-
- .a
- One of the most used size-extension is .a, due to its meaning for the
- adress-handling. This extension is available to many commands. It
- defines the size to be processed to 20 bits (5 nibbles).
-
- .p
- The .p extension tells the command to process the nibble pointed to by
- the p register, therefore accessing one nibble only.
-
- .wp
- This extension tells the command to access the nibbles 0 to p of the
- specified register(s).
-
- .xs
- Accesses the exponent sign: Nibble #2 of the registers.
-
- .x
- Accesses the whole exponent: Three nibbles, nibble 0 to nibble 2 of the
- registers.
-
- .s
- Accesses the sign: Nibble 15 of the registers
-
- .m
- Accesses the mantissa: 12 nibbles, nibble 3 to nibble 14 of the registers.
-
- .b
- Accesses one byte: 2 nibbles, nibble 0 to nibble 1 of the registers.
- These to nibbles are used to hold the exponent (without the exponent
- sign).
-
- .w
- Acesses one complete register or floating-point value: 16 nibbles,
- nibble 0 to nibble 15 of the registers.
-
- If you access the memory by using one of the adress-registers, the
- specified size does not affect the location in memory.
- MOVE.s (d0),c
- MOVE.xs c,(d0)
- do both access the same adress in memory, but they use different
- nibbles of the c register.
-
- In most cases, CLASS will accept the following equivalents:
- .2 = .b
- .3 = .x
- .4 = .as
- .5 = .a
- .16 = .w
-
- 2.2 Size extension graphical summary:
- -------------------------------------
-
- Assuming register p to consist the value 9
-
- --------- Nibble of register ------------------
- 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 Size-extension
- .. .. .. .. .. .. .. .. .. .. .. ** ** ** ** ** .a
- .. .. .. .. .. .. ** .. .. .. .. .. .. .. .. .. .p
- .. .. .. .. .. .. ** ** ** ** ** ** ** ** ** ** .wp
- .. .. .. .. .. .. .. .. .. .. .. .. .. ** .. .. .xs
- .. .. .. .. .. .. .. .. .. .. .. .. .. ** ** ** .x
- ** .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .s
- .. ** ** ** ** ** ** ** ** ** ** ** ** .. .. .. .m
- .. .. .. .. .. .. .. .. .. .. .. .. .. .. ** ** .b
- ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** .w
- The following entries are only valid for the
- MOVE.dd #xxx,a.p|c.p
- command, still assuming p to be 9
- .. .. .. .. .. .. ** .. .. .. .. .. .. .. .. .. .1
- .. .. .. .. .. ** ** .. .. .. .. .. .. .. .. .. .2
- .. .. .. .. ** ** ** .. .. .. .. .. .. .. .. .. .3
- .. .. .. ** ** ** ** .. .. .. .. .. .. .. .. .. .4
- .. .. ** ** ** ** ** .. .. .. .. .. .. .. .. .. .5
- .. ** ** ** ** ** ** .. .. .. .. .. .. .. .. .. .6
- ** ** ** ** ** ** ** .. .. .. .. .. .. .. .. .. .7
- ** ** ** ** ** ** ** .. .. .. .. .. .. .. .. ** .8
- ** ** ** ** ** ** ** .. .. .. .. .. .. .. ** ** .9
- ** ** ** ** ** ** ** .. .. .. .. .. .. ** ** ** .10
- ** ** ** ** ** ** ** .. .. .. .. .. ** ** ** ** .11
- ** ** ** ** ** ** ** .. .. .. .. ** ** ** ** ** .12
- ** ** ** ** ** ** ** .. .. .. ** ** ** ** ** ** .13
- ** ** ** ** ** ** ** .. .. ** ** ** ** ** ** ** .14
- ** ** ** ** ** ** ** .. ** ** ** ** ** ** ** ** .15
- ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** .16
-
- 2.3 Parameters
- --------------
-
- The Clarke-processors commands use up to three parameters. The
- following types of parameters are supported by CLASS:
-
- label A string that defines the name of a label, a numerical
- or one that is a offset to the object-code's begin. Example:
- JMP label
-
- #expr An expression that is calculated while assembling.
- See also chapter 2.4 Example:
- BSET #expr,st
-
- a|b|c|d One of the four data-registers a,b,c and d.
- The '|' sign is used as a logical OR in the following
- Example:
- MOVE a,c
-
- c.dd The nibble pointed to by dd (decimal digit 0 to 15) in c register
-
- c.p The nibbles from the one p points to higher ones in c register
- a.p The nibbles from the one p points to higher ones in a register
-
- rx One of the five scratch-registers r0,r1,r2,r3 and r4
-
- p The p register
-
- st The status-register
-
- hst The harware-status-register
-
- in The I/O input-register
-
- out The I/O output-register
-
- 2.4 Expression evaluation
- -------------------------
-
- Expressions may consist of labels, absolute values, operators
- and parentheses. Expressions are evaluated without any kind
- of hierarchy, you have to set parentheses if required. This behaviour
- may change in future versions of CLASS.
- Numerical labels and those who include an offset to the object's
- begin are treated the same in the actual version. This may also
- change in future.
-
- 2.4.1 Operators
- ---------------
-
- Actually, there are only a few operators supported:
- + Addition
- - Subtraction / negative sign
- * Multiplication
- / Division
- | OR
- & AND
- \ XOR
-
- 2.4.2 Absolute values
- ---------------------
-
- Decimal numbers begin with a number from 0 to 9. 1234
- Hexadecimal numbers are prefixed with an dollar sign. $12ab
- Binary numbers are prefixed with a per-cent sign. %01101
- ASCII-codes are written between quotation marks. "xy12"
-
- 2.5 Adressing modes
- -------------------
-
- The following is a complete (?hope so?) list of the available
- adressing modes:
-
- #expr Absolute value
- label Absolute adress
- a|b|c|d Data-register direct
- (a) Data-register indirect (used in JMP (a) only)
- d0|d1 Adress-register direct
- (d0)|(d1) Adress-register indirect
- r0|r1|r2|r3|r4 Scratch-register direct
- p P-register direct
- st Status-register direct
- hst Hardware-status-register direct
- in I/O input-register direct
- out I/O output-register direct
- c.dd Data-register c with special nibble-pointer
- a|c.p Data-register from nibble pointed to by p register upwards
-
- 2.6 Mnemonic summary
- --------------------
-
- Many of the mnemonics listed here are sharing the format
- mnemonic.size source,dest
- Notice that this is similar to the 680xx family's assembly format,
- and the opposite of Intel's one.
-
- The following abbreviations will be used:
- fs Field selctor. One of the extensions .p, .wp, .xs, .x, .s, .m, .b, .w
- rx One of the five scratch-registers r0,r1,r2,r3,r4
-
- Notice that commands that use the .a size-extension need less nibbles
- to be coded in most cases.
-
- 2.6.1 Data transfer instructions
- --------------------------------
-
- MOVE
- ----
-
- The most used mnemonic at all is the move-command. There are a lot of
- adressing modes available, but they are not very similar to the
- adressing modes used by other processors. In fact, there are
- missing very potent ones like index'ed adressing.
-
- Available:
-
- move.fs|a b|c ,a
- move.fs|a a|c ,b
- move.fs|a a|b|d ,c
- move.fs|a c ,d
-
- move.3 c ,st ; only 12 of the 16 st-bits are affected!
- move.3 st ,c
-
- move.a|4 a|c ,d0|d1 ; move.a|4 d0|d1,a|c does not exist!!!
- ; use exg.a|4 a|c,d0|d1 if required
- move.fs|a|dd a|c ,(d0|d1) ; .a and .b are needing less nibbles
- move.fs|a|dd (d0|d1),a|c ; .a and .b are needing less nibbles
-
- move.w a|c ,rx
- move.w rx ,a|c
- move.fs|a a|c ,rx ; these two need more nibbles than the
- move.fs|a rx ,a|c ; previous - they were implemented later
-
- move.4 in ,a|c ; this instruction fails if it is executed
- ; on an odd adress. A bug in the microcode
- move.3 c ,out
- move.s c ,out ; out high-nibble affected
-
- move.1 p ,c.dd
- move.1 c.dd ,p
-
- move.1 #expr ,p
-
- move.a #expr ,d0|d1
- move.ao #expr ,d0|d1 ; read "RELTAB" description
- move.as #expr ,d0|d1
- move.b #expr ,d0|d1
-
- move.dd #expr ,a.p|c.p ; this instruction is used that often, I
- ; decided to allow 'a' or 'c' as destination
- ; take care of the contents of p !
- move.ao #expr ,a.p|c.p ; read "RELTAB" description
-
- move.a pc ,a|c
-
- EXG
- ---
-
- EXG exchanges the contents of two registers. It makes is no difference
- which register is defined first:
- exg.w c,r0 = exg.w r0,c and so on...
-
- EXG is a very usual instruction on the Clarke processor, it allows to
- use the scratch-registers as quick-accessable data storage and
- it is the only way to move an adressa out of an adress-register.
-
- Available:
-
- exg.w c|a ,rx
- exg.fs|a c|a ,rx ; this one needs more nibbles than the
- ; previous - it were implemented later
-
- exg.a c|a ,d0|d1
-
- exg.fs|a a|b|c ,a|b|c
- exg.fs|a c ,d
-
- exg.1 p ,c.dd
-
- exg.a a|c ,pc
-
- PUSH
- ----
-
- PUSH "pushes" a 20-bit value from register c onto stack.
-
- Available:
-
- push
-
- POP
- ---
-
- POP transfers the top 20-bit of the stack into the lower 20-bit of
- register c.
-
- Available:
-
- pop
-
-
- 2.6.2 Arithmetic instructions
- -----------------------------
-
- ADD
- ---
-
- ADD is just what it is on every micro-processor: It adds two values
- and stores the result in a register. There are powerful increment
- instructions similar to the ADDQ instruction in the 680xx family,
- but I decided to use the same mnemonic, add, for them.
-
- Available:
-
- add.a #expr ,d0|d1 ; expr must be >=1 and <=16
-
- add.fs|a #expr ,a|b|c|d ; expr must be >=1 and <=16. In fact,
- ; only the .b, .x, .a, .m and .w extension
- ; work properly on this instruction.
-
- add.fs|a a|b|c ,a|b|c ; adding one register on itself is allowed!
- add.fs|a c|d ,d|c ; It's then just a shift left one bit!
-
- add.a p+1 ,c ; This one is always done in hex-mode
- ; Wonderful to combine with .wp size extension
- SUB
- ---
-
- SUB subtracts the first parameter from the second and stores the
- result in the register that has to be specified as the second parameter.
-
- Available:
-
- sub.fs|a a|b|c ,a|b|c
- sub.fs|a c|d ,d|c
-
- sub.a #expr ,d0|d1 ; expr must be >=1 and <=16
-
- add.fs|a #expr ,a|b|c|d ; expr must be >=1 and <=16. In fact,
- ; only the .b, .x, .a, .m and .w extension
- ; work properly on this instruction.
-
- SUBR
- ----
-
- SUBR is not available on the 680xx-family. It subtracts the second
- parameter from the first and stores the result in the register that
- has to be specified as the second parameter.
-
- Available:
-
- subr.fs|a b ,a
- subr.fs|a c ,b
- subr.fs|a a ,c
- subr.fs|a c ,d
-
- INC
- ---
-
- INC increases a specified register by one.
-
- Available:
-
- inc.fs|a a|b|c|d
-
- inc.1 p
-
- inc.a d0|d1 ; identical to add.a #1,d0|d1
-
- DEC
- ---
-
- DEC decreases a specified register by one.
-
- Available:
-
- dec.fs|a a|b|c|d
-
- dec.1 p
-
- dec.a d0|d1 ; identical to sub.a #1,d0|d1
-
- CLR
- ---
-
- CLR stores zero into a register.
-
- Available:
-
- clr.3 st ; only the lower 12 bits are cleared!
-
- clr.fs|a a|b|c|d
-
- clr.1 #expr ,hst ; the bits set in expr are cleared in hst
-
- NEG
- ---
-
- NEG converts a registers value into it's 2's complement.
-
- Available:
-
- neg.fs|a a|b|c|d
-
- NOT
- ---
-
- NOT inverts all the bits in a register's field.
-
- Available:
-
- not.fs|a a|b|c|d
-
-
- 2.6.3 Binary-arithmetic instructions
- ------------------------------------
-
- OR
- --
-
- OR bitwise "ors" two registers and stores the result in the second one.
-
- Available:
-
- or.fs|a a|b|c ,a|b|c
- or.fs|a c|d ,d|c
-
- AND
- ---
-
- AND bitwise "ands" two registers and stores the result in the second one.
-
- Available:
-
- and.fs|a a|b|c ,a|b|c
- and.fs|a c|d ,d|c
-
- LSL
- ---
-
- LSL shifts the bits in a register to the left, setting the rightmost
- bit to zero after each shift.
-
- Available:
-
- lsl.fs|a #4 ,a|b|c|d ; a one-nibble shift in fact
- lsl.fs|a #1 ,a|b|c|d ; is identical to add.fs|a a,a|b,b|c,c|d,d
-
- LSR
- ---
-
- LSR shifts the bits in a register to the right, setting the leftmost
- bit to zero after each shift.
-
- Available:
-
- lsr.fs|a #4 ,a|b|c|d ; a one-nibble shift in fact
- lsr.w #1 ,a|b|c|d
- lsr.fs|a #1 ,a|b|c|d ; needs more nibbles than the
- ; previous one - later implemented
-
- ROL
- ---
-
- ROL rotates the bits in a register to the left, setting the rightmost
- bit to the value shifted out
-
- Available:
-
- rol.w #4 ,a|b|c|d ; that's all - sorry
-
- ROR
- ---
-
- ROR rotates the bits in a register to the right, setting the leftmost
- bit to the value shifted out
-
- Available:
-
- ror.w #4 ,a|b|c|d ; that's all - sorry
-
- BSET
- ----
-
- BSET sets a specified bit in a register. It is not possible to use
- this instruction on a bit-number higher than 15. Bit numbers always
- counts from 0, the LSB of the register. There's no size-extension.
-
- Available:
-
- bset #expr ,a|c ; expr must be >=0 and <=15
-
- bset #expr ,st ; expr must be >=0 and <=15
-
- BCLR
- ----
-
- BCLR cleares a specified bit in a register. It is not possible to use
- this instruction on a bit-number higher than 15. Bit numbers always
- counts from 0, the LSB of the register. There's no size-extension.
-
- Available:
-
- bclr #expr ,a|c ; expr must be >=0 and <=15
-
- bclr #expr ,st ; expr must be >=0 and <=15
-
- 2.6.4 Conditional branches
- --------------------------
-
- The instructions that affect the program counter do not differ much
- from those found on other processors. But there are two anomalies:
- Every conditional branch can be also a conditional return-from-
- subroutine by setting the branch-offset to zero.
- Due to the lack of flags, the conditional branches include the
- neccesary test operations.
-
- The following tests are supported:
- eq = equal
- ne != not equal
- lt < lower than
- le <= lower or equal
- gt > greater than
- gs >= greater or equal
-
- There are four other, special tests:
-
- cc carry clear The branch is taken if the carry flag is clear
- cs carry set The branch is taken if the carry flag is set
- bc bit clear The branch is taken if the specified bit is 0
- bs bit set The branch is taken if the specified bit is 1
-
- The label that defines the adress to jump to when the branch is taken,
- must be within a range of -128 to 127 around the adress the offset is
- defined.
-
- Available:
-
- bcc label
- bcs label
- rtcc ; return-if-carry-clear ...
- rtcs
-
- beq.fs|a a|b|c|d,0,label ; branch is taken if register is zero
- bne.fs|a a|b|c|d,0,label ; branch is taken if register is not zero
-
- beq.fs|a a|b|c,a|b|c,label ; branch is taken if registers are equal
- beq.fs|a c|d,d|c,label
-
- rteq.fs|a a|b|c|d,0 ; return if register is zero
- rtne.fs|a a|b|c|d,0
-
- blt.fs|a a|b|c,a|b|c,label ; branch is taken if first register is lower
- blt.fs|a c|d,d|c,label ; than second one
-
- ble.fs|a a|b|c,a|b|c,label
- ble.fs|a c|d,d|c,label
-
- bgt.fs|a a|b|c,a|b|c,label
- bgt.fs|a c|d,d|c,label
-
- bge.fs|a a|b|c,a|b|c,label
- bge.fs|a c|d,d|c,label
-
- rtlt.fs|a a|b|c,a|b|c
- rtlt.fs|a c|d,d|c
-
- rtgt.fs|a a|b|c,a|b|c
- rtgt.fs|a c|d,d|c
-
- rtle.fs|a a|b|c,a|b|c
- rtle.fs|a c|d,d|c
-
- rtge.fs|a a|b|c,a|b|c
- rtge.fs|a c|d,d|c
-
- beq.1 #expr,hst,label ; branch is taken if hst AND expr is zero
- rteq.1 #expr,hst
-
- beq.1 #expr,p,label ; branch is taken if expr is equal to contents
- rteq.1 #expr,p ; of p register
-
- bne.1 #expr,p,label
- rtne.1 #expr,p
-
- bbc #expr,st,label ; branch is taken if specified bit in st is clear
- rtbc #expr,st
-
- bbs #expr,st,label ; branch is taken if specified bit in st is set
- rtbs #expr,st
-
- bbc #expr,a|c,label
- rtbc #expr,a|c
-
- bbs #expr,a|c,label
- rtbs #expr,a|c
-
- 2.6.5 Unconditional branches and other pc manipulation
- ------------------------------------------------------
-
- Please notice: Use relative branches if possible;
- use always the "smallest" jump, that reaches
- the desired adress.
-
- Available:
-
- bra.3 label ; jumps relative (range: -2048 to +2047)
- bra.4 label ; jumps relative (range: -32768 to 32767)
-
- bsr.3 label ; calls subroutine (range: -2048 to +2047)
- bsr.4 label ; calls subroutine (range: -32768 to +32767)
-
- jmp label ; jumps to absolute 20-bit adressa
- jsr label ; calls subroutine at absolute 20-bit adressa
-
- jmp a|c ; jumps to the location pointed to by the lower
- ; 20 bits of the specified register
-
- jmp (a) ; jump to the adress that is defined at the
- ; memory location pointed to by the lower 20 bits
- ; of the specified register
-
- rtnsxm ; return and set XM-flag in hst. Used to catch
- ; "jumps into the desert" (opcode $00)
- rtn ; simply return from subroutine
- rtncc ; return and clear carry
- rtnsc ; return and set carry
-
- rsi ; return from system interrupt. Not fully explored yet
-
- 2.6.6 Miscellaneous instructions
- --------------------------------
-
- sethex ; sets the processor into HEX-Mode
- setdec ; sets the processor into DEC-Mode
-
- Not fully explored yet.
- I do not know exactly how the mode affects the processors work.
-
- nop4 ; an artifical 4-nibble-nop, in fact a senseless branch
-
- uncnfg ; unconfigures all chips (?) and transfers the lower
- ; 20 bits of register c into each chip controller's
- ; data pointer. Not fully explored yet.
- config ; sends the lower 20-bits of register c to the chip
- ; which has daisy chain input high and config flag low
- ; Not fully explored yet
- c=id ; identifies chip: transfers the ID of the chip which has
- ; daisy chain input high and config flag low to the
- ; lower 20 bits of register c
- ; Not fully explored yet
- shutdn ; sends bus-shut-down command and stops CPU-Clock
- inton ; enables some sort of interrupt (from keyboard?)
- intoff ; disables some sort of interrupt (from keyboard?)
- reset ; sends system-bus-reset command, resets chips. Not fully...
- buscc ; sends system-bus command "C". Not fully...
- buscd ; sends system-bus command "D"? Not fully...
- sreq? ; if any chip on bus needs service, SR-bit in hst is set,
- ; and the "device-identifier" is latched to the lowest
- ; nibble of register c
-
-
- 3.0 The CLASS Assembler's pseudo-ops
- ------------------------------------
-
- There are a lot of so called "pseudo-opcodes" supported - instructions
- that are not translated into bits instructing the processor to do something.
-
- 3.1 Include files
- -----------------
-
- Every serious assembler supports include-files. You may type a line
- into your source-code, that has the "include" command in the mnemonic
- field and a filename as a parameter. This file will be inserted
- into the source while assembly. An include-file (which is, of course
- a normal source-file also) may include other files. There's no nesting
- limit but your stack's size.
- Examples:
- include "DH0:blub.a"
- include trash.a
- Notice: Every include-file will increase the number of lines to assemble
- (sounds simple..?)
-
- 3.2 Constants
- -------------
-
- Constants are nibbles created by the assembler that are not executable
- code.
-
- 3.2.1 Nibble-by-nibble constants
- --------------------------------
-
- With the "dc", "dcr" and "dcg" pseudo-ops you can place any kind of data
- into your object-file. The format is:
- dc.dd value, value, value, ...
- dcr.dd value, value, value, ...
- dcg.dd value, value, value, ...
- dd defines the constant's size.
- "dc" puts the values from high- to low-nibble into memory, as it is done
- by the 680xx family for example.
- "dcr" puts the values from low- to high-nibble into memory, this is how
- the Clarke-processor does it. Example:
-
- start move.a #data,d0
- move.a (d0),c
- add.a #5,d0
- move.a (d0),a
- rtn
- data dcr.5 $12345
- dc.5 $12345
-
- After calling this routine, register c will hold $12345 while register a
- contents $54321.
-
- "dcg" is used to define graphic-data for the HP48sx bit-plane format.
- Not only the order of the nibbles is reversed, the bits itself are
- also exchanged. You can shift graphic-data pixel-wise by just shifting
- the register that holds the data. Notice that the bit-plane of the HP48sx
- is organized byte-wise.
-
- 3.2.2 Text-Constants
- --------------------
-
- With the "text" pseudo-ob you can place ASCII-codes into your object file.
- There's another pseudo-ob, "textr", which is used to reverse the nibbles
- of each ASCII. Format:
- text "The quick brown fox jumps over the lazy dog"
- textr "The quick brown fox jumps over the lazy dog"
-
- 3.3 The EQU instruction
- -----------------------
-
- Use the "equ" pseudo-ob to define the value of a label to be created.
- Format:
- label equ expr
- References between label-definitions are solved completely. The following
- example will cause no trouble:
- jim equ bob+jeff-7
- bob equ jeff/2
- jeff equ 6
- The following example will cause trouble:
- jim equ bob+jeff-7
- bob equ jeff/2
- jeff equ jim
-
- >ERROR: Unable to solve reference between following labels:
- >jim
- >bob
- >jeff
-
- 3.4 Macros
- ----------
-
- To define a macro, use this syntax:
-
- name macro para1,para2,para3,para4
- ....
- ....
- endmac
-
- Notice: - You can use any string to define a parameter. It's a good idea
- to choose a string that never occures in normal source-code.
- - The endmac statement must be the only word in the terminating
- line.
- - You cannot nest macros.
- - Macros must be defined BEFORE they are used in the source.
- - Use "?cnt?" to place a unique number for each macro in the
- resulting source
- - The number of possible parameters is limited to 4
- - The total lenght of source-text in a macro is limited to
- 32767 characters
-
- Examples:
-
- rpl macro value
- dcr.5 value
- endmac
-
- absadr macro lbl,reg
- bsr absadr?cnt?
- absadr?cnt? pop
- move.a #lbl-absadr?cnt?,a
- add.a a,c
- move.a c,reg
- endmac
- ; what follows is an example how the macros
- ; are called
- rpl $02d9d
- absadr data,d0
-
- move.3 #$123,c
- move.3 c,(d0)
- ; just an example ... has no meaning
- data text "-----------"
-
- The "absadr"-macro would look like this after expanding:
- bsr absadr1
- absadr1 pop
- move.a #data-absadr1,a
- add.a a,c
- move.a c,d0
-
- 3.5 The relocation-table
- ------------------------
-
- To write programs that are relocated before execution I implemented a
- pseudo-ob called "RELTAB". Use this pseudo to insert a table of the
- following format into your code:
-
- $XXXXX 20-Bit-Offset from PGM's base, where to find first adress to reloc
- $XXXXX 2. adress...
- ... 3. 4. 5. ... adresses
- ...
- $00000 A terminating zero-adress to signal list's end
-
- Entries in this table are made the following way:
- Whenever CLASS faces a valid instruction with a size-extension that is ".ao",
- it calculates the offset from the begin of the program to the adress
- where to find the 20-Bit-adress that is specified within the instruction.
- This adress is held in a variable until the RELTAB instruction is found.
- Then all the adresses collected becomes entries in the relocation table.
- The variables are cleared, and the game starts over.
- You may have more than one relocation-table in one program. But be sure
- to use the right ones for relocation during execution then.
- A sample relocation- and re-relocation-routine comes within the CLASS package.
- It'll fit your needs on a HP48sx.
- Note: A RELTAB command only cares about the adressas that have been specified
- in the source above.
- Be sure to avoid a 48sx-garbage-collection between relocation and
- re-relocation.
- If you fail to re-relocate a program after execution, your system
- may crash the next time you call the program. Avoid unwanted
- interrupts!!!
-
- 4.0 Local labels
- ----------------
-
- The CLASS assembler supports local labels in a very easy way, to explain
- how to use them I will simply explain what CLASS does:
-
- Whenever CLASS finds a label that does end with an "." character, it
- assumes this label to be global. It stores the name of such a label
- in special variable.
- Whenever CLASS encounters a label with an "." as FIRST character, it
- takes the name of the last global label from the special variable,
- apends the name of the local label (including the point) and adds
- another point at the end of the total name.
-
- This is the whole thing. Now look what you can do with it...
-
- start text "the example starts here with a global label"
- bra .1 ; a first reference to a local label
- text "just a filler"
- later. ; a label that has been inserted later.
- ; it is a global one, but it does not
- ; affect the last-global-name variable
- text "just a filler"
- .1
- text "this would be the destination of the branch"
- .jimbob
- text "local label names are normal strings..."
- ende ; the end of the routine, a global label
- dc.5 start.1. ;access local label from an outer point...
- .1 ; you can use ".1" as label name again...
- dc.5 later. ; a reference to the later inserted label
- bra .1 ; this jump goes to ende.1.
-
- 5.0 Invocation
- --------------
-
- The invocation of the CLASS assembler depends on the
- computer-type you use.
-
- 5.1 Invoking CLASS on Commodore's AMIGA
- ---------------------------------------
-
- You have to invoke CLASS from a command-line interpreter. Use the
- following format:
-
- CLASS -a SOURCENAME [-o OBJECTNAME] [-i INCLUDE_DIR] [-ml maximal_lines]
- [-mm maximal_macros] [-ul] [-rn] [-mr maximal_reloctab_entries]
- [-s SYMBOL_FILE]
-
- Upper-case parameters have to be replaced by a string, lower-case ones
- have to be replaced by a decimal number.
- Parameters in parentheses are optional
-
- -a Defines the name of the source file
- -o Defines the name of the object file
- -i Defines the name of the include file directory (the actual path
- is searched also)
- -s Defines the name of an optinal symbol-file (e.g. for use with CLDIS)
- -ml Defines the maximal number of source-lines
- -mm Defines the maximal number of macro-definitions
- -mr Defines the maximal number of reloction-table-entries (view "RELTAB")
- -ul Enables listing of unused labels at the end of assembly
- -rn Enables nibble-swapping at end of assembly. Requiered if you use
- a "dumb" KERMIT-program that doesn't the swapping.
-
- 5.2 Invoking CLASS on Atari's ST
- --------------------------------
-
- After having started CLASS.TTP from either the desktop or any CLI
- you can use the same set of options discussed under 5.1.
-
- To hold screen after execution keep mouse-key pressed.
-
- Please do not use external screen output accelerators like
- NVDI, TurboST or QuickST for there may occur pixel-trash then.
-
- 6.0 Bugs and future extensions
- ------------------------------
-
- This is a early release of CLASS. I'm sure there are bugs
- in it. Please report any bug you find to me (adress: see below).
- I'm also happy about any good idea for additional features.
-
- 6.1 Known Bugs
- --------------
-
- - CLASS is not that fast. I have not optimized
- the code in any other way than saving programming-time now.
- - CLASS is not able to handle expressions that exceed the 32 bits a
- 68000 is able to hold in a register. There are only two instructions
- where this disadvantage can cause problems: move.dd #expr,c.p|a.p
- If you really need to use such an instruction with more than 8
- nibbles, you can replace it manually:
-
- move.16 #$0123456789abcdef,c.p
-
- can be replaced by:
-
- dc.1 $3,16-1
- dc.8 $fedcba98,$76543210
-
-
- move.16 #$0123456789abcdef,a.p
-
- can be replaced by:
-
- dc.4 $8082
- dc.1 16-1
- dc.8 $fedcba98,$76543210
-
- Maybe I'll find the motivation to process 64-bit-values later, but
- I don't think it's that neccessary.
-
- 6.2 New features to come
- ------------------------
-
- - More speed
- - A more different bahavior of numeric and offset labels
- - Conditional assembly
- - More useful pseudo-ops
-
- Since this program is not published the commercial way, I cannot
- guarantee updates at all.
-
- 7.0 Trademarks
- --------------
-
- Amiga : Commodore-Amiga Inc., USA
- Atari ST : Atari
- HP48sx : Hewlett Packard, USA
-
- 8.0 Adress of the author
- ------------------------
-
- Please contact me via EMail.
-
- UseNet : lv@muffel.hotb.sub.org
- FidoNet: 2:247/30.20
-
- If it seems VERY urgent, and you cannot use EMAIL, call
- -49-69-5601966 (voice)
-
- Appendices:
- -----------
-
- A. HP48sx Processor Performance - explored by L. Vieweg May 1991
- ----------------------------------------------------------------
-
- A.1.0 The cycle period
- ----------------------
-
- The HP48sx Clarke-processor clock runs at 1.96 MHz (in my machine).
- About 25% of the processors speed is cut off when you enable the
- BitPlane DMA. To run your processor at full speed, clear bit 3 at
- $00100.
-
- A.2.0 Instruction execution times
- ---------------------------------
-
- These are the execution times of the Clarke processor's
- most used instructions. This list may be completed or revised later.
- Notice: If there are fractional cycles given, calculate the total
- cycles first, then round the number (7.5 => 8 and so on...).
- The abbreviation "siz" means the total number of nibbles
- affected by an instruction (.s=1, .b=2, .x=3, .a=5, .w=16, ...)
- Refer to the CLASS-assembler's manual for further information.
-
- Add one cycle for each odd adress the pc runs through. This will
- cause some nasty effects when programming time-critical routines.
-
- Instruction Source Dest Cycles
- -----------------------------------------------------------------
- move.dd #0 ,c.p 2.5+dd*1.5
-
- normal / access $00100-$0013f
- move.dd (d1)|(d0) ,c|a 21.5+dd*1.5 / 21+dd
- move.fs (d1)|(d0) ,c|a 21.5+siz*1.5 / 21+siz
- move.b (d1)|(d0) ,c|a 19 /17
- move.a (d1)|(d0) ,c|a 23 /20
-
- move.a c|a ,(d0)|(d1) 19
- move.b c|a ,(d0)|(d1) 16
- move.fs c|a ,(d0)|(d1) 20+siz
- move.dd c|a ,(d0)|(d1) 20+siz
-
- move.a a ,c 8
- move.fs a|b|c|d ,a|b|c|d 4+siz
-
- move.a a|c ,d0|d1 9
- move.4 a|c ,d0|d1 8
-
- move.w a|c ,rx 20
- move.w rx ,a|c 20
-
- move.1 p ,c.dd 8
- move.1 c.dd ,p 8
-
- move.1 #expr ,p 3
-
- move.a #expr ,d0|d1 10
- move.as #expr ,d0|d1 9
- move.b #expr ,d0|d1 6
-
- clr.fs a|b|c|d 4+siz
- clr.a a|b|c|d 8
-
- clr.1 #expr ,hst 4
-
- exg.w c|a ,rx 20
- exg.a c|a ,d0|d1 9
-
- exg.fs a|b|c|d ,a|b|c|d 4+siz
- exg.a a|b|c|d ,a|b|c|d 8
-
- exg.1 p ,c.dd 8
-
- push pop 18 (the two's total)
-
- add.a #expr ,d0|d1 8
-
- add.fs a|b|c|d ,a|b|c|d 4+siz
- add.a a|b|c|d ,a|b|c|d 8
-
- add.a p+1 ,c 9
-
- sub.fs a|b|c|d ,a|b|c|d 4+siz
- sub.a a|b|c|d ,a|b|c|d 8
- subr.fs a|b|c|d ,a|b|c|d 4+siz
- subr.a a|b|c|d ,a|b|c|d 8
-
- sub.a #expr ,d0|d1 8
-
- inc.fs a|b|c|d 4+siz
- inc.a a|b|c|d 8
- dec.fs a|b|c|d 4+siz
- dec.a a|b|c|d 8
-
- inc.1 p 4
-
- neg.fs a|b|c|d 4+siz
- neg.a a|b|c|d 8
-
- not.fs a|b|c|d 4+siz
- not.a a|b|c|d 8
-
- or.fs a|b|c|d ,a|b|c|d 6+siz
- or.a a|b|c|d ,a|b|c|d 11
-
- and.fs a|b|c|d ,a|b|c|d 6+siz
- and.a a|b|c|d ,a|b|c|d 11
-
- lsl.fs #4 ,a|b|c|d 5+siz
- lsl.a #4 ,a|b|c|d 9
-
- lsr.fs #4 ,a|b|c|d 5+siz
- lsr.a #4 ,a|b|c|d 9
-
- lsr.w #1 ,a|b|c|d 21
-
- rol.w #4 ,a|b|c|d 22
- ror.w #4 ,a|b|c|d 22
-
- bset #expr ,a|c 8
- bclr #expr ,a|c 8
-
- bsr.3 rtn 26 (the two's total)
- bsr.4 rtn 29
-
- bra.3 14
- bra.4 17
-
- ; taken/not taken
- bcc.2 12/4
-
- b??.fs a|b|c|d ,a|b|c|d|0 16+siz/8+siz
- b??.a a|b|c|d ,a|b|c|d|0 21/13
-
- beq.1 #expr ,hst 16/8
-
- beq.1 #expr ,p 17/9
-
- bbc|bbs #expr ,a|c 20/12
-
- A.3.0 Overall Performance Comment
- ---------------------------------
-
- The processor's speed isn't very impressive. There's especially
- one point of criticism to the developers I wish to say:
- Everyone knows it's not possible to run handhelds processor clocks at
- a high speed because of the temperature-problems that would cause
- massive battery exhaust when semi-conductors get hot. But if so,
- why the devil have you created such a cycle-eating micro-code?
- There are so many nice processors around that do not need that much
- cycles for each intruction (6800, 65xx, 8510 etc., even the Z80 needs
- less cycles...), why does your's do????
-
- The Clarke processor is able to move large amounts of data quicker
- through memory than comparable processors because of it's 64-bit
- registers. It is also fast on doing simple floating-point operations
- (I'll explore the decimal-mode later...). But it is very slow
- on more complex tasks as array-accessing, fixed-point operations
- and parameter-passing to subroutines (the little stack...).
-
-