flat assembler
Message board for the users of flat assembler.
Index
> Non-x86 architectures > HP Saturn |
Author |
|
ldbeth 19 Nov 2022, 18:14
I'm trying to build a cross assembler for HP50g calculator. 50g (and 49g) runs a HP Saturn emulator on 32bit ARMv4T. Although it is possible to run ARM on 50g, the entire OS is still based on the emulated HP Saturn instruction set. HP Saturn itself is nibble addressed, which can be demonstrated by this example program
Code: 1 * -*- mode:sasm -*- 2 00000 31FF LCHEX FF 3 00004 A6E LOOP C=C-1 B 4 00007 5CF GONC LOOP 5 0000A 143 A=DAT1 A 6 0000D 164 D0=D0+ 5 7 00010 808C PC=(A) 8 00014 END The assembly language is in the simple Code: Label Mnemonic Argument Comment I could imaging it is possible to write each nibble as a byte, and do a post processing step to merge nearby two nibbles into one byte, my question would be if I can do that post processing in fasmg. The output format would be a header contains the number of nibbles in program, a block of machine codes, and a symbol table. There is an open source assembler for HP Saturn written in C that also works for HP50g, but that was mainly targeted to HP48 series which lacks support to opcode exclusive to ARM emulated models, so it is only suitable for compiling System RPL which is essentially a variant of Forth which only requires the assembler to link with the symbol table to form a series of pointers. All the opcode of HP Saturn are recorded at https://www.hpcalc.org/details/1693, including those specific to ARM based models. The conventional mnemonics are not likely to work with fasmg, as arith symbols are involved, but I think I'm ok with come up a new set of mnemonics. |
|||
19 Nov 2022, 18:14 |
|
Tomasz Grysztar 19 Nov 2022, 21:03
ldbeth wrote: I could imaging it is possible to write each nibble as a byte, and do a post processing step to merge nearby two nibbles into one byte, my question would be if I can do that post processing in fasmg. The output format would be a header contains the number of nibbles in program, a block of machine codes, and a symbol table. The most classic one is to generate instructions into a virtual block, and then finally convert it into actual output: Code: Header dd code.nibbles ; etc. virtual at 0 code:: postpone code.nibbles = $ if $ and 1 db 0 end if end virtual repeat (code.nibbles+1)/2 load low:byte from code:(%-1)*2 load high:byte from code:(%-1)*2+1 db low + high shl 4 end repeat end postpone Code: code:: postpone ? code.nibbles = $ if $ and 1 db 0 end if restartout Header dd code.nibbles ; etc. repeat (code.nibbles+1)/2 load low:byte from code:(%-1)*2 load high:byte from code:(%-1)*2+1 db low + high shl 4 end repeat end postpone Also, instead of postponing the conversion, you could implement the instructions to use a macro to output nibbles, which would lay them out into bytes immediately. And you can re-define the $ symbol to give a nibble-granular address: Code: $nibble = 0 $ equ ($? shl 1 - $nibble) ; $? allows to access built-in symbol instead of this re-defined one macro nibble values& iterate n, values if $nibble = 1 load tmp : byte from $?-1 store tmp or (n) shl 4 : byte at $?-1 else db n end if $nibble = $nibble xor 1 end iterate end macro The engine is flexible and there are many directions you could consider - but whichever variant you choose, it is going to require careful design and some relatively complex macros. The examples I've given here are very simplified. |
|||
19 Nov 2022, 21:03 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.