less terrible instruction generation
This commit is contained in:
4
Makefile
4
Makefile
@ -79,14 +79,14 @@ test: ${OUT}
|
||||
clean:
|
||||
-rm ${OUT} ${OBJECT} ${GENOBJECT} ${GENSOURCE}
|
||||
|
||||
${OBJECT.d}/%.pp: debug/%.tcl
|
||||
${OBJECT.d}/%.pp: debug/%.tcl debug/instructions.tcl
|
||||
tclsh $< > $@
|
||||
|
||||
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 -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 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
|
||||
|
@ -1,6 +1,5 @@
|
||||
set instructions {
|
||||
{syscall}
|
||||
{nop}
|
||||
{sysret}
|
||||
{sysexit}
|
||||
{sysenter}
|
||||
@ -10,6 +9,30 @@ set instructions {
|
||||
{pause}
|
||||
{hlt}
|
||||
{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}
|
||||
|
@ -1,62 +1,71 @@
|
||||
source debug/instructions.tcl
|
||||
|
||||
proc make_parser_rules {is} {
|
||||
proc type_name_to_type_enum {n} {
|
||||
switch $n {
|
||||
"register" {
|
||||
return "REG"
|
||||
proc init_iarg {a n} {
|
||||
set r [dict create]
|
||||
switch $a {
|
||||
"register" {
|
||||
dict set r enum "REG"
|
||||
dict set r value "\$$n.number"
|
||||
dict set r size "\$$n.size"
|
||||
}
|
||||
"immediate" {
|
||||
return "IMM"
|
||||
dict set r enum "IMM"
|
||||
dict set r value "(int)$e"
|
||||
dict set r size "32"
|
||||
}
|
||||
"memory" {
|
||||
return "MEM"
|
||||
}
|
||||
default {
|
||||
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
|
||||
"memory" {
|
||||
dict set r enum "MEM"
|
||||
dict set r value "0 /* ??? */"
|
||||
dict set r size "0 /* ??? */"
|
||||
}
|
||||
default { malformed_instruction $n }
|
||||
}
|
||||
return $r
|
||||
}
|
||||
proc make_parser_rule {i} {
|
||||
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]]
|
||||
]
|
||||
} elseif {[llength $i] == 3} {
|
||||
set rule [format " | I%s %s %s \{ append_instruction_t4(\
|
||||
%s,\
|
||||
\$2.size,\
|
||||
} elseif {[llength $i] == 2} {
|
||||
set arg [init_iarg [lindex $i 1] 2]
|
||||
set rule [format " | IT%s %s \{ append_instruction_t4(\
|
||||
%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]] \
|
||||
[lindex $i 1] \
|
||||
[lindex $i 2] \
|
||||
\
|
||||
[string toupper [lindex $i 0]] \
|
||||
[type_name_to_type_enum [lindex $i 1]] \
|
||||
[type_name_to_type_value [lindex $i 1] "\$2"] \
|
||||
[type_name_to_type_enum [lindex $i 2]] \
|
||||
[type_name_to_type_value [lindex $i 2] "\$3"] \
|
||||
[dict get $arg1 size] \
|
||||
[dict get $arg1 enum] \
|
||||
[dict get $arg1 value] \
|
||||
[dict get $arg2 enum] \
|
||||
[dict get $arg2 value] \
|
||||
]
|
||||
} else {
|
||||
malformed_instruction $i
|
||||
|
@ -2,7 +2,7 @@ source debug/instructions.tcl
|
||||
|
||||
proc make_scanner_instructions {is} {
|
||||
proc make_scanner_instruction {i} {
|
||||
puts [format "%s { return I%s; }" \
|
||||
puts [format "%s { return IT%s; }" \
|
||||
[lindex $i 0] \
|
||||
[string toupper [lindex $i 0]]
|
||||
]
|
||||
@ -12,4 +12,6 @@ proc make_scanner_instructions {is} {
|
||||
}
|
||||
}
|
||||
|
||||
puts " */"
|
||||
|
||||
make_scanner_instructions $instructions
|
||||
|
@ -1,9 +1,16 @@
|
||||
source debug/instructions.tcl
|
||||
|
||||
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"
|
||||
foreach i $is {
|
||||
puts -nonewline [format " I%s" [string toupper [lindex $i 0]]]
|
||||
foreach i [uniq_instl $is] {
|
||||
puts -nonewline [format " IT%s" [string toupper [lindex $i 0]]]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,8 +103,8 @@ u64 { return U64; }
|
||||
|
||||
\" { BEGIN IN_STRING; }
|
||||
|
||||
\!\= { return NEQ; }
|
||||
\! { return TNOT; }
|
||||
\!\= { return ITNEQ; }
|
||||
\! { return ITNOT; }
|
||||
|
||||
\/\/ { BEGIN IN_COMMENT; }
|
||||
\/\* { BEGIN IN_MULTILINE_COMMENT; }
|
||||
@ -116,15 +116,45 @@ u64 { return U64; }
|
||||
fastcall { return FASTCALL; }
|
||||
|
||||
/* --- Instrunctions begin here --- */
|
||||
/*
|
||||
xor{wsnl}+ { return TXOR; }
|
||||
inc{wsnl}+ { return TINC; }
|
||||
nop { return INOP; }
|
||||
/* #placeholder<scanner_instructions> BEGIN
|
||||
*/
|
||||
add { return IADD; }
|
||||
syscall { return ISYSCALL; }
|
||||
mov { return IMOV; }
|
||||
xor { return IXOR; }
|
||||
/* #placeholder<scanner_instructions> COLLAPSED
|
||||
syscall { return ITSYSCALL; }
|
||||
sysret { return ITSYSRET; }
|
||||
sysexit { return ITSYSEXIT; }
|
||||
sysenter { return ITSYSENTER; }
|
||||
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 --- */
|
||||
|
||||
|
@ -52,9 +52,9 @@
|
||||
%token UNIX WIN64
|
||||
|
||||
// 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
|
||||
@ -79,13 +79,10 @@
|
||||
%token RG8D RG9D RG10D RG11D RG12D RG13D RG14D RG15D
|
||||
|
||||
// Instructions
|
||||
%token TADD TOR TADC TBB TXOR TAND TSUB TCMP TSYSCALL TINC
|
||||
%token INOP // better temp prefix?
|
||||
%token IADD
|
||||
%token ISYSCALL
|
||||
%token IMOV
|
||||
%token IXOR
|
||||
// #placeholder<token_list> COLLAPSED
|
||||
%token INOP
|
||||
// #placeholder<token_list> BEGIN
|
||||
%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
|
||||
// #placeholder<token_list> END
|
||||
|
||||
// Instruction-likes
|
||||
%token FASTCALL
|
||||
@ -208,28 +205,6 @@ code: %empty
|
||||
| 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
|
||||
;
|
||||
|
||||
@ -237,13 +212,13 @@ if: IF logic THEN code END_IF
|
||||
| IF logic THEN code ELSE code END_IF
|
||||
;
|
||||
|
||||
logic: logical_operand TAND logical_operand
|
||||
| logical_operand TOR logical_operand
|
||||
| logical_operand TXOR logical_operand
|
||||
| logical_operand '=' logical_operand
|
||||
| logical_operand NEQ logical_operand
|
||||
logic: logical_operand ITAND logical_operand
|
||||
| logical_operand ITOR logical_operand
|
||||
| logical_operand ITXOR logical_operand
|
||||
| logical_operand '=' logical_operand
|
||||
| logical_operand ITNEQ logical_operand
|
||||
| sublogic
|
||||
| TNOT logic
|
||||
| ITNOT logic
|
||||
;
|
||||
|
||||
logical_operand: sublogic
|
||||
@ -345,4 +320,49 @@ artimetric_operand: LITERAL
|
||||
|
||||
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
|
||||
;
|
||||
|
||||
%%
|
||||
|
Reference in New Issue
Block a user