Posted: Thu 15 Dec, 2005 5:51 pm
The issue is more backwards compatibility with TASM than me adding new features to Brass, sadly.Jim e wrote:Well beyond asking ben to make a SUPER intelligent way of handleing macros...
for your 1 bit pleasure!
https://maxcoderz.org/forum/
The issue is more backwards compatibility with TASM than me adding new features to Brass, sadly.Jim e wrote:Well beyond asking ben to make a SUPER intelligent way of handleing macros...
Very nice, thanksJim e wrote:I wrote most of an interrupt routines like mirageos's that can handle several things, i try to post later today, after I fully test it.
Code: Select all
; Assume a function called 'square_root', which takes acc. as the argument:
#define square_root(value) ld a,value \ call square_root
#ifdef Brass
.define square_root({a}) call square_root
#endif
Code: Select all
; put_s_fixed will display a string: hl->string, b=length
#define draw_string(string, length) ld b,length \ ld hl,string \ call put_s_fixed
#ifdef Brass
.define draw_string({hl}, {b}) call put_s_fixed
.define draw_string(string, {b}) ld hl,string \ call put_s_fixed
.define draw_string({hl}, length) ld b,length \ call put_s_fixed
#endif
Code: Select all
load(reg, value) ld reg,value
load({a},{0}) xor a
load({a},{a})
load({de},{hl}) ld d,h \ ld e,l
compare(value) cp value
compare({0}) or a
Code: Select all
#ifdef brass
.define load(reg,{reg}) ; makes sure value gets in a if it isn't already
; Add your exceptions for double registers / ld a,0 / ld a,a etc..
#else
#define load(reg,value) ld reg,value
#endif
#define square_root(value) load(a,value) \ call square_root
Code: Select all
#ifdef brass
.define load({a},{0}) xor a
.define load({a},{a})
.define load({a},value) ld a,value
.define load({b},{b})
.define load({b},value) ld b,value
.define load({c},{c})
.define load({c},value) ld c,value
.define load({h},{h})
.define load({h},value) ld h,value
.define load({l},{l})
.define load({l},value) ld l,value
.define load({d},{d})
.define load({d},value) ld d,value
.define load({e},{e})
.define load({e},value) ld e,value
.define load({hl},{hl})
.define load({hl},{de}) ld h,d \ ld l,e
.define load({hl},{bc}) ld h,b \ ld l,c
... etc
#else
#define load(reg,value) ld reg,value
#endif
Not sure. Brass is, but doesn't support backwards referencing on macros (so load() would have to have been defined before square_root()).Timendus wrote:Hey, that's a pretty cool idea. Would using macro's withing macro definitions be possible with TASM? Then we could do something like:
That would keep the code readable for API users.Code: Select all
#ifdef brass .define load(reg,{reg}) ; makes sure value gets in a if it isn't already ; Add your exceptions for double registers / ld a,0 / ld a,a etc.. #else #define load(reg,value) ld reg,value #endif #define square_root(value) load(a,value) \ call square_root
Brass would do some matching between the different macros and try and find the most specific one it can use. Hence in my examples I don't use an #else block, I always use the TASM macro as the most generic macro definition to fall back on if none of the special cases are matched.You have to explain to me what the curly braces will do exactely though. If I have a macro like load({a},{0}), and I supply it with another register than a for it's first argument, it will load the contents of that register in a? And if I supply some other value than 0 for it's second argument the macro will not be parsed, so it can be taken care of by another macro?
Code: Select all
.define load(reg,{reg}) ; makes sure value gets in a if it isn't already
Code: Select all
load (*,reg)
Okay, those are two things I'll have to test. If I recall correctly TASM will use the first macro with a certain name, and ignore the rest, but I'm not sure about that. If so, we wouldn't even need to #define brass. TASM would use the first macro, and Brass would have more specific macro's that handle optimization cases.benryves wrote:Not sure. Brass is, but doesn't support backwards referencing on macros (so load() would have to have been defined before square_root()).
Brass would do some matching between the different macros and try and find the most specific one it can use. Hence in my examples I don't use an #else block, I always use the TASM macro as the most generic macro definition to fall back on if none of the special cases are matched.
As I said, sorry, this'll take a while to be implemented. I'm really busy at the moment...Timendus wrote:It's so useful to have our own compiler programmer I'm glad you decided to write your own assembler, Ben
Don't worry, that's no problem. I'm really busy myself, so testing this and preparing for the Brass adaption if it turns out to be possible will take quite some time too. And I still haven't added everthing I want to add, I haven't fixed the potential greyscale bug yet, my own thingy is still far from finished...benryves wrote:As I said, sorry, this'll take a while to be implemented. I'm really busy at the moment...
I do have a more up-to-date build as it is, but it's got more bugs than the current release that I haven't got around to fixing (it's got to the "huge, messy, difficult to maintain" stage in places, so a lot of work has just been in invisible refactoring changes). *sighs*Timendus wrote:And I think Latenite should have a higher priority
Code: Select all
; ***
; [routine]load(reg,val)[/routine]
;
; Loads a value or a register <i>val</i> in register <i>reg</i>.
;
; <i>It is recommended that (within this API) this macro is only used in other macro definitions where the input is variable, not in API routines! The API should stay compatible with TASM as much as possible!</i>
;
; In TASM, this macro will just compile to
; <kbd>ld reg,val</kdb>
; but when compiled with Brass, exceptions will assure that things like these work too:
; <kdb>load(bc,a)
; load(hl,ix)
; load(ix,iyh)</kbd>
; and that things like these will be optimized:
; <kbd>load(h,h) compiles to nothing
; load(a,0) compiles to xor a</kbd>
;
; <b>Note:</b> In some special cases like these:
; <kbd>load(h,ixh)
; load(iy,hl)</kdb>
; the neccessary exception macro's will use register <i>a</i> or the stack as a temporary storage.
;
; Written by:
; Timendus
;
;****************************************
; TASM/default define
#define load(reg,val) ld reg,val
;****************************************
; Exceptions for single registers
#define load({a},{0}) xor a
#define load({a},{a})
#define load({b},{b})
#define load({c},{c})
#define load({d},{d})
#define load({e},{e})
#define load({h},{h})
#define load({l},{l})
#define load({ixh},{ixh})
#define load({ixl},{ixl})
#define load({iyh},{iyh})
#define load({iyl},{iyl})
#define load({h},{ixh}) ld a,ixh \ ld h,a
#define load({h},{ixl}) ld a,ixl \ ld h,a
#define load({h},{iyh}) ld a,iyh \ ld h,a
#define load({h},{iyl}) ld a,iyl \ ld h,a
#define load({l},{ixh}) ld a,ixh \ ld l,a
#define load({l},{ixl}) ld a,ixl \ ld l,a
#define load({l},{iyh}) ld a,iyh \ ld l,a
#define load({l},{iyl}) ld a,iyl \ ld l,a
#define load({ixh},{h}) ld a,h \ ld ixh,a
#define load({ixh},{l}) ld a,l \ ld ixh,a
#define load({ixl},{h}) ld a,h \ ld ixl,a
#define load({ixl},{l}) ld a,l \ ld ixl,a
#define load({iyh},{h}) ld a,h \ ld iyh,a
#define load({iyh},{l}) ld a,l \ ld iyh,a
#define load({iyl},{h}) ld a,h \ ld iyl,a
#define load({iyl},{l}) ld a,l \ ld iyl,a
;****************************************
; Exceptions for HL
#define load({hl},{hl})
#define load({hl},{a}) ld h,0 \ ld l,a
#define load({hl},{b}) ld h,0 \ ld l,b
#define load({hl},{c}) ld h,0 \ ld l,c
#define load({hl},{d}) ld h,0 \ ld l,d
#define load({hl},{e}) ld h,0 \ ld l,e
#define load({hl},{h}) ld l,h \ ld h,0
#define load({hl},{l}) ld h,0
#define load({hl},{ixh}) load(hl,ix) \ ld l,h \ ld h,0
#define load({hl},{ixl}) load(hl,ix) \ ld h,0
#define load({hl},{iyh}) load(hl,iy) \ ld l,h \ ld h,0
#define load({hl},{iyl}) load(hl,iy) \ ld h,0
#define load({hl},{de}) ld h,d \ ld l,e
#define load({hl},{bc}) ld h,b \ ld l,c
#define load({hl},{ix}) push ix \ pop hl
#define load({hl},{iy}) push iy \ pop hl
;****************************************
; Exceptions for DE
#define load({de},{de})
#define load({de},{a}) ld d,0 \ ld e,a
#define load({de},{b}) ld d,0 \ ld e,b
#define load({de},{c}) ld d,0 \ ld e,c
#define load({de},{d}) ld e,d \ ld d,0
#define load({de},{e}) ld d,0
#define load({de},{h}) ld d,0 \ ld e,h
#define load({de},{l}) ld d,0 \ ld e,l
#define load({de},{ixh}) ld d,0 \ ld e,ixh
#define load({de},{ixl}) ld d,0 \ ld e,ixl
#define load({de},{iyh}) ld d,0 \ ld e,iyh
#define load({de},{iyl}) ld d,0 \ ld e,iyl
#define load({de},{hl}) ld d,h \ ld e,l
#define load({de},{bc}) ld d,b \ ld e,c
#define load({de},{ix}) ld d,ixh \ ld e,ixl
#define load({de},{iy}) ld d,iyh \ ld e,iyl
;****************************************
; Exceptions for BC
#define load({bc},{bc})
#define load({bc},{a}) ld b,0 \ ld c,a
#define load({bc},{b}) ld c,b \ ld b,0
#define load({bc},{c}) ld b,0
#define load({bc},{d}) ld b,0 \ ld c,d
#define load({bc},{e}) ld b,0 \ ld c,e
#define load({bc},{h}) ld b,0 \ ld c,h
#define load({bc},{l}) ld b,0 \ ld c,l
#define load({bc},{ixh}) ld b,0 \ ld c,ixh
#define load({bc},{ixl}) ld b,0 \ ld c,ixl
#define load({bc},{iyh}) ld b,0 \ ld c,iyh
#define load({bc},{iyl}) ld b,0 \ ld c,iyl
#define load({bc},{hl}) ld b,h \ ld c,l
#define load({bc},{de}) ld b,d \ ld c,e
#define load({bc},{ix}) ld b,ixh \ ld c,ixl
#define load({bc},{iy}) ld b,iyh \ ld c,iyl
;****************************************
; Exceptions for IX
#define load({ix},{ix})
#define load({ix},{a}) ld ixh,0 \ ld ixl,a
#define load({ix},{b}) ld ixh,0 \ ld ixl,b
#define load({ix},{c}) ld ixh,0 \ ld ixl,c
#define load({ix},{d}) ld ixh,0 \ ld ixl,d
#define load({ix},{e}) ld ixh,0 \ ld ixl,e
#define load({ix},{ixh}) ld ixl,ixh \ ld ixh,0
#define load({ix},{ixl}) ld ixh,0
#define load({ix},{iyh}) load(ix,iy) \ load(ix,ixh)
#define load({ix},{iyl}) load(ix,iy) \ load(ix,ixl)
#define load({ix},{hl}) push hl \ pop ix
#define load({ix},{de}) ld ixh,d \ ld ixl,e
#define load({ix},{bc}) ld ixh,b \ ld ixl,c
#define load({ix},{iy}) push iy \ pop ix
;****************************************
; Exceptions for IY
#define load({iy},{iy})
#define load({iy},{a}) ld iyh,0 \ ld iyl,a
#define load({iy},{b}) ld iyh,0 \ ld iyl,b
#define load({iy},{c}) ld iyh,0 \ ld iyl,c
#define load({iy},{d}) ld iyh,0 \ ld iyl,d
#define load({iy},{e}) ld iyh,0 \ ld iyl,e
#define load({iy},{ixh}) load(iy,ix) \ load(iy,iyh)
#define load({iy},{ixl}) load(iy,ix) \ load(iy,iyl)
#define load({iy},{iyh}) ld iyl,iyh \ ld iyh,0
#define load({iy},{iyl}) ld iyh,0
#define load({iy},{hl}) push hl \ pop iy
#define load({iy},{de}) ld iyh,d \ ld iyl,e
#define load({iy},{bc}) ld iyh,b \ ld iyl,c
#define load({iy},{ix}) push ix \ pop iy
;****************************************
;****************************************
Code: Select all
#define sqrt(var) load(a,var)
#defcont \ call sqr_root
.org 0
start:
; Some examples of macro in macro definition use:
sqrt(10) ; compiles to ld a,10 \ call sqr_root in Brass
sqrt(a) ; compiles to call sqr_root in Brass
sqrt(0) ; compiles to xor a \ call sqr_root in Brass
sqrt(b) ; compiles to ld a,b \ call sqr_root in Brass
; These give errors in TASM, not in Brass:
load(hl,ix)
load(bc,a)
; These are unoptimized in TASM, not in Brass:
load(c,c)
load(a,0)
sqr_root:
ret
stop:
.echo "*** Binary size: "
.echo stop-start
.echo " bytes\n"
.end