less terrible instruction generation

This commit is contained in:
anon
2024-07-12 16:51:21 +02:00
parent 204fe84052
commit 543b4d3c8a
7 changed files with 181 additions and 90 deletions

View File

@ -79,14 +79,14 @@ test: ${OUT}
clean: clean:
-rm ${OUT} ${OBJECT} ${GENOBJECT} ${GENSOURCE} -rm ${OUT} ${OBJECT} ${GENOBJECT} ${GENSOURCE}
${OBJECT.d}/%.pp: debug/%.tcl ${OBJECT.d}/%.pp: debug/%.tcl debug/instructions.tcl
tclsh $< > $@ tclsh $< > $@
plug: ${OBJECT.d}/token_list.pp ${OBJECT.d}/scanner_instructions.pp ${OBJECT.d}/parser_rules.pp plug: ${OBJECT.d}/token_list.pp ${OBJECT.d}/scanner_instructions.pp ${OBJECT.d}/parser_rules.pp
plug -u -d token_list '' -d scanner_instructions '' -d parser_rules '' source/eaxhla.l source/eaxhla.y plug -u -d token_list '' -d scanner_instructions '' -d parser_rules '' source/eaxhla.l source/eaxhla.y
plug -g -e token_list ${OBJECT.d}/token_list.pp source/eaxhla.y plug -g -e token_list ${OBJECT.d}/token_list.pp source/eaxhla.y
plug -g -e scanner_instructions ${OBJECT.d}/scanner_instructions.pp source/eaxhla.l plug -g -e scanner_instructions ${OBJECT.d}/scanner_instructions.pp source/eaxhla.l
plug -g -e parser_rules ${OBJECT.d}/parser_rules.pp source/eaxhla.l plug -g -e parser_rules ${OBJECT.d}/parser_rules.pp source/eaxhla.y
.PHONY: test clean bootstrap .PHONY: test clean bootstrap

View File

@ -1,6 +1,5 @@
set instructions { set instructions {
{syscall} {syscall}
{nop}
{sysret} {sysret}
{sysexit} {sysexit}
{sysenter} {sysenter}
@ -10,6 +9,30 @@ set instructions {
{pause} {pause}
{hlt} {hlt}
{lock} {lock}
{inc register}
{dec register}
{not register}
{neg register}
{mul register}
{imul register}
{div register}
{idiv register}
{inc memory}
{dec memory}
{not memory}
{neg memory}
{mul memory}
{imul memory}
{div memory}
{idiv memory}
{add register register}
{or register register}
{adc register register}
{sbb register register}
{and register register}
{sub register register}
{xor register register}
{cmp register register}
} }
# {mov register immediate} # {mov register immediate}

View File

@ -1,62 +1,71 @@
source debug/instructions.tcl source debug/instructions.tcl
proc make_parser_rules {is} { proc make_parser_rules {is} {
proc type_name_to_type_enum {n} { proc init_iarg {a n} {
switch $n { set r [dict create]
"register" { switch $a {
return "REG" "register" {
dict set r enum "REG"
dict set r value "\$$n.number"
dict set r size "\$$n.size"
} }
"immediate" { "immediate" {
return "IMM" dict set r enum "IMM"
dict set r value "(int)$e"
dict set r size "32"
} }
"memory" { "memory" {
return "MEM" dict set r enum "MEM"
} dict set r value "0 /* ??? */"
default { dict set r size "0 /* ??? */"
malformed_instruction $n
}
}
}
proc type_name_to_type_value {n e} {
switch $n {
"register" {
return "$e.number"
}
"immediate" {
return "(int)$e"
}
"memory" {
return "???"
}
default {
malformed_instruction $n
} }
default { malformed_instruction $n }
} }
return $r
} }
proc make_parser_rule {i} { proc make_parser_rule {i} {
if {[llength $i] == 1} { if {[llength $i] == 1} {
set rule [format " | I%s { append_instruction_t1(%s); }" \ set rule [format " | IT%s { append_instruction_t1(%s); }" \
[string toupper [lindex $i 0]] \
[string toupper [lindex $i 0]] \ [string toupper [lindex $i 0]] \
[string toupper [lindex $i 0]]
] ]
} elseif {[llength $i] == 3} { } elseif {[llength $i] == 2} {
set rule [format " | I%s %s %s \{ append_instruction_t4(\ set arg [init_iarg [lindex $i 1] 2]
%s,\ set rule [format " | IT%s %s \{ append_instruction_t4(\
\$2.size,\
%s,\ %s,\
%s,\ %s,\
%s,\ %s,\
%s\ %s\
);" \ ); \}" \
[string toupper [lindex $i 0]] \
[lindex $i 1] \
\
[string toupper [lindex $i 0]] \
[dict get $arg size] \
[dict get $arg enum] \
[dict get $arg value] \
]
} elseif {[llength $i] == 3} {
set arg1 [init_iarg [lindex $i 1] 2]
set arg2 [init_iarg [lindex $i 2] 3]
set rule [format " | IT%s %s %s \{ append_instruction_t6(\
%s,\
%s,\
%s,\
%s,\
%s,\
%s\
); \}" \
[string toupper [lindex $i 0]] \ [string toupper [lindex $i 0]] \
[lindex $i 1] \ [lindex $i 1] \
[lindex $i 2] \ [lindex $i 2] \
\ \
[string toupper [lindex $i 0]] \ [string toupper [lindex $i 0]] \
[type_name_to_type_enum [lindex $i 1]] \ [dict get $arg1 size] \
[type_name_to_type_value [lindex $i 1] "\$2"] \ [dict get $arg1 enum] \
[type_name_to_type_enum [lindex $i 2]] \ [dict get $arg1 value] \
[type_name_to_type_value [lindex $i 2] "\$3"] \ [dict get $arg2 enum] \
[dict get $arg2 value] \
] ]
} else { } else {
malformed_instruction $i malformed_instruction $i

View File

@ -2,7 +2,7 @@ source debug/instructions.tcl
proc make_scanner_instructions {is} { proc make_scanner_instructions {is} {
proc make_scanner_instruction {i} { proc make_scanner_instruction {i} {
puts [format "%s { return I%s; }" \ puts [format "%s { return IT%s; }" \
[lindex $i 0] \ [lindex $i 0] \
[string toupper [lindex $i 0]] [string toupper [lindex $i 0]]
] ]
@ -12,4 +12,6 @@ proc make_scanner_instructions {is} {
} }
} }
puts " */"
make_scanner_instructions $instructions make_scanner_instructions $instructions

View File

@ -1,9 +1,16 @@
source debug/instructions.tcl source debug/instructions.tcl
proc make_token_list {is} { proc make_token_list {is} {
proc uniq_instl {is} {
set r []
foreach i $is {
lappend r [lindex $i 0]
}
return [lsort -unique $r]
}
puts -nonewline "%token" puts -nonewline "%token"
foreach i $is { foreach i [uniq_instl $is] {
puts -nonewline [format " I%s" [string toupper [lindex $i 0]]] puts -nonewline [format " IT%s" [string toupper [lindex $i 0]]]
} }
} }

View File

@ -103,8 +103,8 @@ u64 { return U64; }
\" { BEGIN IN_STRING; } \" { BEGIN IN_STRING; }
\!\= { return NEQ; } \!\= { return ITNEQ; }
\! { return TNOT; } \! { return ITNOT; }
\/\/ { BEGIN IN_COMMENT; } \/\/ { BEGIN IN_COMMENT; }
\/\* { BEGIN IN_MULTILINE_COMMENT; } \/\* { BEGIN IN_MULTILINE_COMMENT; }
@ -116,15 +116,45 @@ u64 { return U64; }
fastcall { return FASTCALL; } fastcall { return FASTCALL; }
/* --- Instrunctions begin here --- */ /* --- Instrunctions begin here --- */
/* nop { return INOP; }
xor{wsnl}+ { return TXOR; } /* #placeholder<scanner_instructions> BEGIN
inc{wsnl}+ { return TINC; }
*/ */
add { return IADD; } syscall { return ITSYSCALL; }
syscall { return ISYSCALL; } sysret { return ITSYSRET; }
mov { return IMOV; } sysexit { return ITSYSEXIT; }
xor { return IXOR; } sysenter { return ITSYSENTER; }
/* #placeholder<scanner_instructions> COLLAPSED leave { return ITLEAVE; }
retf { return ITRETF; }
retn { return ITRETN; }
pause { return ITPAUSE; }
hlt { return ITHLT; }
lock { return ITLOCK; }
inc { return ITINC; }
dec { return ITDEC; }
not { return ITNOT; }
neg { return ITNEG; }
mul { return ITMUL; }
imul { return ITIMUL; }
div { return ITDIV; }
idiv { return ITIDIV; }
inc { return ITINC; }
dec { return ITDEC; }
not { return ITNOT; }
neg { return ITNEG; }
mul { return ITMUL; }
imul { return ITIMUL; }
div { return ITDIV; }
idiv { return ITIDIV; }
add { return ITADD; }
or { return ITOR; }
adc { return ITADC; }
sbb { return ITSBB; }
and { return ITAND; }
sub { return ITSUB; }
xor { return ITXOR; }
cmp { return ITCMP; }
/* #placeholder<scanner_instructions> END
*/ */
/* --- Instrunctions end here --- */ /* --- Instrunctions end here --- */

View File

@ -52,9 +52,9 @@
%token UNIX WIN64 %token UNIX WIN64
// Logic // Logic
%token NEQ TNOT %token ITNEQ
/* /*
%token TOR TXOR // these are (in)conveniently instructions too %token ITOR ITXOR ITAND ITNOT // these are (in)conveniently instructions too
*/ */
// Type info // Type info
@ -79,13 +79,10 @@
%token RG8D RG9D RG10D RG11D RG12D RG13D RG14D RG15D %token RG8D RG9D RG10D RG11D RG12D RG13D RG14D RG15D
// Instructions // Instructions
%token TADD TOR TADC TBB TXOR TAND TSUB TCMP TSYSCALL TINC %token INOP
%token INOP // better temp prefix? // #placeholder<token_list> BEGIN
%token IADD %token ITADC ITADD ITAND ITCMP ITDEC ITDIV ITHLT ITIDIV ITIMUL ITINC ITLEAVE ITLOCK ITMUL ITNEG ITNOT ITOR ITPAUSE ITRETF ITRETN ITSBB ITSUB ITSYSCALL ITSYSENTER ITSYSEXIT ITSYSRET ITXOR
%token ISYSCALL // #placeholder<token_list> END
%token IMOV
%token IXOR
// #placeholder<token_list> COLLAPSED
// Instruction-likes // Instruction-likes
%token FASTCALL %token FASTCALL
@ -208,28 +205,6 @@ code: %empty
| instruction code | instruction code
; ;
instruction: INOP { ; }
/*
| TXOR register register code { /* assemble_xor(size_64b, type_register_register, $2, $3); * / }
| TXOR register immediate code { /* assemble_xor(size_64b, type_register_register, $2, $3); * / }
| TXOR IDENTIFIER register code { /* assemble_xor(size_64b, type_register_register, $2, $3); * / free($2); }
| TINC register code
| TINC IDENTIFIER code { free($2); }
*/
| IADD register register
| IADD register immediate
| IADD register memory
| ISYSCALL { append_instruction_t1 (SYSCALL); }
| IMOV register register
| IMOV memory register
| IMOV register memory
| IMOV register immediate { append_instruction_t6 (MOV, $2.size, REG, $2.number, IMM, (int) $3); }
| IMOV memory immediate
| IXOR register register
| IXOR register memory
// #placeholder<parser_rules> COLLAPSED
;
repeat: REPEAT code END_REPEAT repeat: REPEAT code END_REPEAT
; ;
@ -237,13 +212,13 @@ if: IF logic THEN code END_IF
| IF logic THEN code ELSE code END_IF | IF logic THEN code ELSE code END_IF
; ;
logic: logical_operand TAND logical_operand logic: logical_operand ITAND logical_operand
| logical_operand TOR logical_operand | logical_operand ITOR logical_operand
| logical_operand TXOR logical_operand | logical_operand ITXOR logical_operand
| logical_operand '=' logical_operand | logical_operand '=' logical_operand
| logical_operand NEQ logical_operand | logical_operand ITNEQ logical_operand
| sublogic | sublogic
| TNOT logic | ITNOT logic
; ;
logical_operand: sublogic logical_operand: sublogic
@ -345,4 +320,49 @@ artimetric_operand: LITERAL
exit: EXIT value exit: EXIT value
; ;
instruction: INOP { append_instruction_t1(NOP); }
/*
| ISYSCALL { append_instruction_t1 (SYSCALL); }
| IMOV register immediate { append_instruction_t6 (MOV, $2.size, REG, $2.number, IMM, (int) $3); }
*/
// #placeholder<parser_rules> BEGIN
| ITSYSCALL { append_instruction_t1(SYSCALL); }
| ITSYSRET { append_instruction_t1(SYSRET); }
| ITSYSEXIT { append_instruction_t1(SYSEXIT); }
| ITSYSENTER { append_instruction_t1(SYSENTER); }
| ITLEAVE { append_instruction_t1(LEAVE); }
| ITRETF { append_instruction_t1(RETF); }
| ITRETN { append_instruction_t1(RETN); }
| ITPAUSE { append_instruction_t1(PAUSE); }
| ITHLT { append_instruction_t1(HLT); }
| ITLOCK { append_instruction_t1(LOCK); }
| ITINC register { append_instruction_t4( INC, $2.size, REG, $2.number ); }
| ITDEC register { append_instruction_t4( DEC, $2.size, REG, $2.number ); }
| ITNOT register { append_instruction_t4( NOT, $2.size, REG, $2.number ); }
| ITNEG register { append_instruction_t4( NEG, $2.size, REG, $2.number ); }
| ITMUL register { append_instruction_t4( MUL, $2.size, REG, $2.number ); }
| ITIMUL register { append_instruction_t4( IMUL, $2.size, REG, $2.number ); }
| ITDIV register { append_instruction_t4( DIV, $2.size, REG, $2.number ); }
| ITIDIV register { append_instruction_t4( IDIV, $2.size, REG, $2.number ); }
| ITINC memory { append_instruction_t4( INC, 0 /* ??? */, MEM, 0 /* ??? */ ); }
| ITDEC memory { append_instruction_t4( DEC, 0 /* ??? */, MEM, 0 /* ??? */ ); }
| ITNOT memory { append_instruction_t4( NOT, 0 /* ??? */, MEM, 0 /* ??? */ ); }
| ITNEG memory { append_instruction_t4( NEG, 0 /* ??? */, MEM, 0 /* ??? */ ); }
| ITMUL memory { append_instruction_t4( MUL, 0 /* ??? */, MEM, 0 /* ??? */ ); }
| ITIMUL memory { append_instruction_t4( IMUL, 0 /* ??? */, MEM, 0 /* ??? */ ); }
| ITDIV memory { append_instruction_t4( DIV, 0 /* ??? */, MEM, 0 /* ??? */ ); }
| ITIDIV memory { append_instruction_t4( IDIV, 0 /* ??? */, MEM, 0 /* ??? */ ); }
| ITADD register register { append_instruction_t6( ADD, $2.size, REG, $2.number, REG, $3.number ); }
| ITOR register register { append_instruction_t6( OR, $2.size, REG, $2.number, REG, $3.number ); }
| ITADC register register { append_instruction_t6( ADC, $2.size, REG, $2.number, REG, $3.number ); }
| ITSBB register register { append_instruction_t6( SBB, $2.size, REG, $2.number, REG, $3.number ); }
| ITAND register register { append_instruction_t6( AND, $2.size, REG, $2.number, REG, $3.number ); }
| ITSUB register register { append_instruction_t6( SUB, $2.size, REG, $2.number, REG, $3.number ); }
| ITXOR register register { append_instruction_t6( XOR, $2.size, REG, $2.number, REG, $3.number ); }
| ITCMP register register { append_instruction_t6( CMP, $2.size, REG, $2.number, REG, $3.number ); }
// #placeholder<parser_rules> END
;
%% %%